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使用socket向客户端发送数据的方法
Apr 29 Python
Python中map和列表推导效率比较实例分析
Jun 17 Python
python 添加用户设置密码并发邮件给root用户
Jul 25 Python
Python+Wordpress制作小说站
Apr 14 Python
python获取指定字符串中重复模式最高的字符串方法
Jun 29 Python
Python设计模式之备忘录模式原理与用法详解
Jan 15 Python
pandas 缺失值与空值处理的实现方法
Oct 12 Python
浅谈在JupyterNotebook下导入自己的模块的问题
Apr 16 Python
2021年的Python 时间轴和即将推出的功能详解
Jul 27 Python
Python 如何测试文件是否存在
Jul 31 Python
python如何设置静态变量
Sep 07 Python
python requests模块的使用示例
Apr 07 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学习 计数器实例代码
2008/06/15 PHP
基于jquery的表格排序
2010/09/11 Javascript
firefox浏览器不支持innerText的解决方法
2013/08/07 Javascript
JS获取html对象的几种方式介绍
2013/12/05 Javascript
JavaScript保留两位小数的2个自定义函数
2014/05/05 Javascript
jQuery取id有.的值的方法
2014/05/21 Javascript
jquery实现的省市区三级联动
2015/04/02 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
JS实现三级折叠菜单特效,其它级可自动收缩
2015/08/06 Javascript
详解javascript实现瀑布流列式布局
2016/01/29 Javascript
理解javascript模块化
2016/03/28 Javascript
动态JavaScript所造成一些你不知道的危害
2016/09/25 Javascript
BootStrap注意事项小结(五)表单
2017/03/10 Javascript
基于jquery实现五星好评
2017/11/18 jQuery
Node.Js生成比特币地址代码解析
2018/04/21 Javascript
vue中组件通信的八种方式(值得收藏!)
2019/08/09 Javascript
js实现拾色器插件(ColorPicker)
2020/05/21 Javascript
解决vue scoped html样式无效的问题
2020/10/24 Javascript
微信小程序实现锚点跳转
2020/11/23 Javascript
快速解决PyCharm无法引用matplotlib的问题
2018/05/24 Python
Python3爬虫学习之将爬取的信息保存到本地的方法详解
2018/12/12 Python
python字典setdefault方法和get方法使用实例
2019/12/25 Python
pycharm配置QtDesigner的超详细方法
2021/01/25 Python
详解python的xlwings库读写excel操作总结
2021/02/26 Python
html5跨域通讯之postMessage的用法总结
2013/11/07 HTML / CSS
美国在线咖啡、茶和餐厅供应商:LollicupStore
2018/05/04 全球购物
Boom手表官网:瑞典手表品牌,设计你的手表
2019/03/11 全球购物
雷曼兄弟的五金店:Lehman’s Hardware Store
2019/04/10 全球购物
日本酒店、民宿、温泉旅馆、当地旅行团中文预订:e路东瀛
2019/12/09 全球购物
机械专业毕业生自荐信
2013/11/02 职场文书
食品销售计划书
2014/04/26 职场文书
毕业大学生自荐信
2014/06/17 职场文书
高中生个性发展自我评价
2015/03/09 职场文书
《称赞》教学反思
2016/02/17 职场文书
测量JavaScript函数的性能各种方式对比
2021/04/27 Javascript
Netflix《海贼王》真人版剧集多张片场照曝光
2022/04/04 日漫