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的线程来解决生产者消费问题的示例
Apr 02 Python
一篇文章快速了解Python的GIL
Jan 12 Python
pandas多级分组实现排序的方法
Apr 20 Python
python实现对csv文件的列的内容读取
Jul 04 Python
解决新django中的path不能使用正则表达式的问题
Dec 18 Python
python linecache 处理固定格式文本数据的方法
Jan 08 Python
python3人脸识别的两种方法
Apr 25 Python
pyqt5实现绘制ui,列表窗口,滚动窗口显示图片的方法
Jun 20 Python
Python基于Opencv来快速实现人脸识别过程详解(完整版)
Jul 11 Python
pycharm重命名文件的方法步骤
Jul 29 Python
Python3 解决读取中文文件txt编码的问题
Dec 20 Python
pymysql 插入数据 转义处理方式
Mar 02 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
php结合飞信 免费天气预报短信
2009/05/07 PHP
php根据年月获取季度的方法
2014/03/31 PHP
PHP实现的DES加密解密实例代码
2016/04/06 PHP
在PHP 7下安装Swoole与Yar,Yaf的方法教程
2017/06/02 PHP
DWR Ext 加载数据
2009/03/22 Javascript
JavaScript原型及原型链终极详解
2016/01/04 Javascript
JS+CSS实现鼠标经过弹出一个DIV框完整实例(带缓冲动画渐变效果)
2016/03/25 Javascript
javascript实现列表切换效果
2016/05/02 Javascript
实例讲解JavaScript的Backbone.js框架中的View视图
2016/05/05 Javascript
Bootstrap+jfinal实现省市级联下拉菜单
2016/05/30 Javascript
js 截取或者替换字符串中的数字实现方法
2016/06/13 Javascript
AngularJS基础 ng-mouseleave 指令详解
2016/08/02 Javascript
jQuery插件autocomplete使用详解
2017/02/04 Javascript
Javascript中字符串相关常用的使用方法总结
2017/03/13 Javascript
JavaScript实现元素滚动条到达一定位置循环追加内容
2017/12/28 Javascript
React组件refs的使用详解
2018/02/09 Javascript
jquery轻量级数字动画插件countUp.js使用详解
2019/10/17 jQuery
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
用Nodejs实现在终端中炒股的实现
2020/10/18 NodeJs
浅谈nuxtjs校验登录中间件和混入(mixin)
2020/11/06 Javascript
three.js显示中文字体与tween应用详析
2021/01/04 Javascript
在Mac OS上搭建Python的开发环境
2015/12/24 Python
浅谈python类属性的访问、设置和删除方法
2016/07/25 Python
python中利用await关键字如何等待Future对象完成详解
2017/09/07 Python
Python简单爬虫导出CSV文件的实例讲解
2018/07/06 Python
python+requests实现接口测试的完整步骤
2020/10/27 Python
python中常用的数据结构介绍
2021/01/12 Python
python中使用np.delete()的实例方法
2021/02/01 Python
浅谈移动端网页图片预加载方案
2018/11/05 HTML / CSS
Vans(范斯)德国官网:美国南加州的原创极限运动潮牌
2017/05/02 全球购物
升国旗仪式主持词
2014/03/19 职场文书
节约用电标语
2014/06/17 职场文书
2014年学前班工作总结
2014/12/08 职场文书
2015学校年度工作总结
2015/05/11 职场文书
三八妇女节主持词
2015/07/04 职场文书
变长双向rnn的正确使用姿势教学
2021/05/31 Python