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中AND、OR的一个使用小技巧
Feb 18 Python
Python 爬虫的工具列表大全
Jan 31 Python
Python处理Excel文件实例代码
Jun 20 Python
详解python3中zipfile模块用法
Jun 18 Python
Python实现在某个数组中查找一个值的算法示例
Jun 27 Python
python中join()方法介绍
Oct 11 Python
python实现贪吃蛇小游戏
Mar 21 Python
Python3.5内置模块之shelve模块、xml模块、configparser模块、hashlib、hmac模块用法分析
Apr 27 Python
python 动态调用函数实例解析
Oct 21 Python
解决TensorFlow程序无限制占用GPU的方法
Jun 30 Python
python中逻辑与或(and、or)和按位与或异或(&、|、^)区别
Aug 05 Python
删除pycharm鼠标右键快捷键打开项目的操作
Jan 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
php提交表单时判断 if($_POST[submit])与 if(isset($_POST[submit])) 的区别
2011/02/08 PHP
php用户注册信息验证正则表达式
2015/11/12 PHP
Laravel框架用户登陆身份验证实现方法详解
2017/09/14 PHP
Laravel框架实现的使用smtp发送邮件功能示例
2019/03/12 PHP
win10下 php安装seaslog扩展的详细步骤
2020/12/04 PHP
onpropertypchange
2006/07/01 Javascript
JS动态创建Table,Tr,Td并赋值的具体实现
2013/07/05 Javascript
javascript显示中文日期的方法
2015/06/18 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
2016/05/10 Javascript
jQuery+ajax读取并解析XML文件的方法
2016/09/09 Javascript
解析jquery easyui tree异步加载子节点问题
2017/03/08 Javascript
详解vue-cli中的ESlint配置文件eslintrc.js
2017/09/25 Javascript
jQuery实现获取及设置CSS样式操作详解
2018/09/05 jQuery
jQuery.parseJSON()函数详解
2019/02/28 jQuery
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
vue 解决异步数据更新问题
2019/10/29 Javascript
基于Vue实现微前端的示例代码
2020/04/24 Javascript
JS实现多选框的操作
2020/06/24 Javascript
python基础教程之循环介绍
2014/08/29 Python
python多线程编程中的join函数使用心得
2014/09/02 Python
Python计算一个文件里字数的方法
2015/06/15 Python
python实现可视化动态CPU性能监控
2018/06/21 Python
Django框架使用富文本编辑器Uedit的方法分析
2018/07/31 Python
正确理解Python中if __name__ == '__main__'
2019/01/24 Python
Pandas聚合运算和分组运算的实现示例
2019/10/17 Python
python实现指定ip端口扫描方式
2019/12/17 Python
Python实现手绘图效果实例分享
2020/07/22 Python
Django mysqlclient安装和使用详解
2020/09/17 Python
大学生通用个人的自我评价
2014/02/10 职场文书
公司授权委托书样本
2014/09/15 职场文书
毕业证委托书范文
2014/09/26 职场文书
2015年话务员工作总结
2015/04/29 职场文书
2016年度基层党建工作公开承诺书
2016/03/25 职场文书
如何写好竞聘报告
2019/04/03 职场文书
员工工作失职检讨书范文!
2019/07/03 职场文书
七年级作文之环保作文
2019/10/17 职场文书