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基础之getpass模块详细介绍
Aug 10 Python
pandas使用get_dummies进行one-hot编码的方法
Jul 10 Python
NumPy 数学函数及代数运算的实现代码
Jul 18 Python
Python实现的连接mssql数据库操作示例
Aug 17 Python
对Python Class之间函数的调用关系详解
Jan 23 Python
Python实现去除列表中重复元素的方法总结【7种方法】
Feb 16 Python
由面试题加深对Django的认识理解
Jul 19 Python
微信小程序python用户认证的实现
Jul 29 Python
python中bytes和str类型的区别
Oct 21 Python
浅谈keras中loss与val_loss的关系
Jun 22 Python
基于python实现银行管理系统
Apr 20 Python
Python数据处理的三个实用技巧分享
Apr 01 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 Document 代码注释规范
2009/04/13 PHP
IIS下PHP的三种配置方式对比
2014/11/20 PHP
验证坐标在某坐标区域内php代码
2016/10/08 PHP
PHP依赖注入原理与用法分析
2018/08/21 PHP
JS创建优美的页面滑动块效果 - Glider.js
2007/09/27 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
用jQuery实现一些导航条切换,显示隐藏的实例代码
2013/06/08 Javascript
ZeroClipboard插件实现多浏览器复制功能(支持firefox、chrome、ie6)
2014/08/30 Javascript
jQuery的选择器中的通配符[id^='code']或[name^='code']及jquery选择器总结
2015/12/24 Javascript
js计算系统当前日期是星期几的方法
2016/07/14 Javascript
jQuery实现简单的手风琴效果
2020/04/17 jQuery
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
AngularJS遍历获取数组元素的方法示例
2017/11/11 Javascript
JavaScript对象拷贝与赋值操作实例分析
2018/12/10 Javascript
详解react-refetch的使用小例子
2019/02/15 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
[38:21]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS LGD-CDEC
2014/05/22 DOTA
[41:05]Serenity vs Pain 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:28]国服启动器接入蒸汽平台操作流程视频
2021/03/11 DOTA
python连接mysql并提交mysql事务示例
2014/03/05 Python
Python命令行参数解析模块getopt使用实例
2015/04/13 Python
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
2015/04/25 Python
Python使用xlrd模块操作Excel数据导入的方法
2015/05/26 Python
详解重置Django migration的常见方式
2019/02/15 Python
Laravel+Dingo/Api 自定义响应的实现
2019/02/17 Python
python爬虫 猫眼电影和电影天堂数据csv和mysql存储过程解析
2019/09/05 Python
Python实现打包成库供别的模块调用
2020/07/13 Python
Python 里最强的地图绘制神器
2021/03/01 Python
会计自我鉴定范文
2013/10/06 职场文书
大学生活动总结怎么写
2014/04/29 职场文书
旅游饭店管理专业自荐书
2014/06/28 职场文书
电话客服专员岗位职责
2014/06/28 职场文书
绿色小区申报材料
2014/08/22 职场文书
自主招生自荐信格式范文
2015/03/25 职场文书
工作简报怎么写
2015/07/21 职场文书
Nginx 根据URL带的参数转发的实现
2021/04/01 Servers