python学习之hook钩子的原理和使用


Posted in Python onOctober 25, 2018

什么是钩子

之前有转一篇关于回调函数的文章

钩子函数、注册函数、回调函数,他们的概念其实是一样的。
钩子函数,顾名思义,就是把我们自己实现的hook函数在某一时刻挂接目标挂载点上。

1. hook函数,就是我们自己实现的函数,函数类型与挂载点匹配(返回值,参数列表)
2. 挂接,也就是hook或者叫注册(register),使得hook函数对目标可用
3. 目标挂载点,也就是挂我们hook函数的地方(我们想在这个目标点实现我们自己的功能)

先看一张图:

 python学习之hook钩子的原理和使用

hook的概念在windows的消息响应机制里面体现的尤为明显。可能我们大家有写过windows桌面相关的程序(像MFC),里面有各种消息监听响应机制。比如,要监听鼠标左键是否按下这个事件,我们要去实现一个onLeftKeyDown()之类的方法,该方法可以称为钩子函数。同时,我们还要去注册钩子函数,MFC中是通过一组宏来实现的。这样当鼠标左键按下后,就能调到我们定义的方法了。

为什么需要钩子

大家思考一下上面这个例子,左键按下方法具体的逻辑是由框架自身去实现,还是由我们用户(调用者)去实现呢?显然应该由我们自己去实现。要提供通用的框架能力,框架自身去实现该方法功能,是没有意义的,所以框架给提供一个挂载的point,把具体逻辑的实现交给用户就好了,灵活可用。

钩子使用

hook是一个编程机制,与语言无关。这里给个python的简单例子,帮助大家理解:

import time

class LazyPerson(object):
  def __init__(self, name):
    self.name = name
    self.watch_tv_func = None
    self.have_dinner_func = None

  def get_up(self):
    print("%s get up at:%s" % (self.name, time.time()))

  def go_to_sleep(self):
    print("%s go to sleep at:%s" % (self.name, time.time()))

  def register_tv_hook(self, watch_tv_func):
    self.watch_tv_func = watch_tv_func

  def register_dinner_hook(self, have_dinner_func):
    self.have_dinner_func = have_dinner_func

  def enjoy_a_lazy_day(self):

    # get up
    self.get_up()
    time.sleep(3)
    # watch tv
    # check the watch_tv_func(hooked or unhooked)
    # hooked
    if self.watch_tv_func is not None:
      self.watch_tv_func(self.name)
    # unhooked
    else:
      print("no tv to watch")
    time.sleep(3)
    # have dinner
    # check the have_dinner_func(hooked or unhooked)
    # hooked
    if self.have_dinner_func is not None:
      self.have_dinner_func(self.name)
    # unhooked
    else:
      print("nothing to eat at dinner")
    time.sleep(3)
    self.go_to_sleep()

def watch_daydayup(name):
  print("%s : The program ---day day up--- is funny!!!" % name)

def watch_happyfamily(name):
  print("%s : The program ---happy family--- is boring!!!" % name)

def eat_meat(name):
  print("%s : The meat is nice!!!" % name)


def eat_hamburger(name):
  print("%s : The hamburger is not so bad!!!" % name)


if __name__ == "__main__":
  lazy_tom = LazyPerson("Tom")
  lazy_jerry = LazyPerson("Jerry")
  # register hook
  lazy_tom.register_tv_hook(watch_daydayup)
  lazy_tom.register_dinner_hook(eat_meat)
  lazy_jerry.register_tv_hook(watch_happyfamily)
  lazy_jerry.register_dinner_hook(eat_hamburger)
  # enjoy a day
  lazy_tom.enjoy_a_lazy_day()
  lazy_jerry.enjoy_a_lazy_day()

代码运行结果:

Tom get up at:1509246940.32
Tom : The program ---day day up--- is funny!!!
Tom : The meat is nice!!!
Tom go to sleep at:1509246949.34
Jerry get up at:1509246949.34
Jerry : The program ---happy family--- is boring!!!
Jerry : The hamburger is not so bad!!!
Jerry go to sleep at:1509246958.37

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python使用urllib2模块抓取HTML页面资源的实例分享
May 03 Python
Python使用Pycrypto库进行RSA加密的方法详解
Jun 06 Python
Mac中Python 3环境下安装scrapy的方法教程
Oct 26 Python
tensorflow实现图像的裁剪和填充方法
Jul 27 Python
Django 中间键和上下文处理器的使用
Mar 17 Python
pycharm 安装JPype的教程
Aug 08 Python
pytorch制作自己的LMDB数据操作示例
Dec 18 Python
python中提高pip install速度
Feb 14 Python
paramiko使用tail实时获取服务器的日志输出详解
Dec 06 Python
细说NumPy数组的四种乘法的使用
Dec 18 Python
tensorboard 可视化之localhost:6006不显示的解决方案
May 22 Python
python异步的ASGI与Fast Api实现
Jul 16 Python
基于Python实现定时自动给微信好友发送天气预报
Oct 25 #Python
python批量修改图片后缀的方法(png到jpg)
Oct 25 #Python
python bmp转换为jpg 并删除原图的方法
Oct 25 #Python
virtualenv 指定 python 解释器的版本方法
Oct 25 #Python
解决python3读取Python2存储的pickle文件问题
Oct 25 #Python
python 解压pkl文件的方法
Oct 25 #Python
纯用NumPy实现神经网络的示例代码
Oct 24 #Python
You might like
15种PHP Encoder的比较
2007/03/06 PHP
PHP分页详细讲解(有实例)
2013/10/30 PHP
php数组去重实例及分析
2013/11/26 PHP
mantis安装、配置和使用中的问题小结
2014/07/14 PHP
PHP+Apache+Mysql环境搭建教程
2016/08/01 PHP
php版微信公众号接口实现发红包的方法
2016/10/14 PHP
php+js实现的无刷新下载文件功能示例
2019/08/23 PHP
JavaScript中判断函数是new还是()调用的区别说明
2011/04/07 Javascript
JavaScript栏目列表隐藏/显示简单实现
2013/04/03 Javascript
Javascript封装DOMContentLoaded事件实例
2014/06/12 Javascript
javascript中数组方法汇总
2015/07/07 Javascript
14款经典网页图片和文字特效的jQuery插件-前端开发必备
2015/08/25 Javascript
JS实现点击按钮获取页面高度的方法
2015/11/02 Javascript
详解AngularJS验证、过滤器、指令
2017/01/04 Javascript
移动端web滚动分页的实现方法
2017/05/05 Javascript
Bootstrap Table 删除和批量删除
2017/09/22 Javascript
使用javaScript实现鼠标拖拽事件
2020/04/03 Javascript
JS中移除非数字最多保留一位小数
2018/05/09 Javascript
webpack项目轻松混用css module的方法
2018/06/12 Javascript
vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
2018/10/24 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
2020/03/12 Javascript
Vue组件简易模拟实现购物车
2020/12/21 Vue.js
通过Python 获取Android设备信息的轻量级框架
2017/12/18 Python
查看django执行的sql语句及消耗时间的两种方法
2018/05/29 Python
对Python定时任务的启动和停止方法详解
2019/02/19 Python
Python如何实现转换URL详解
2019/07/02 Python
django自定义模板标签过程解析
2019/12/14 Python
python3.8动态人脸识别的实现示例
2020/09/21 Python
详解canvas.toDataURL()报错的解决方案全都在这了
2020/03/31 HTML / CSS
我的大学生活职业生涯规划
2014/01/02 职场文书
庆元旦文艺演出主持词
2014/03/27 职场文书
电脑售后服务承诺书
2014/03/27 职场文书
施工工地安全标语
2014/06/07 职场文书
Python读取文件夹下的所有文件实例代码
2021/04/02 Python
vue选项卡切换的实现案例
2022/04/11 Vue.js
正则表达式基础与常用验证表达式
2022/06/16 Javascript