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列表的常用操作方法小结
May 21 Python
Python优化技巧之利用ctypes提高执行速度
Sep 11 Python
Python实现将罗马数字转换成普通阿拉伯数字的方法
Apr 19 Python
Python实现Smtplib发送带有各种附件的邮件实例
Jun 05 Python
使用python根据端口号关闭进程的方法
Nov 06 Python
pandas读取csv文件,分隔符参数sep的实例
Dec 12 Python
Python画图实现同一结点多个柱状图的示例
Jul 07 Python
Python collections模块使用方法详解
Aug 28 Python
Python网络编程之使用TCP方式传输文件操作示例
Nov 01 Python
python模式 工厂模式原理及实例详解
Feb 11 Python
解决Opencv+Python cv2.imshow闪退问题
Apr 24 Python
使用numpy nonzero 找出非0元素
May 14 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
新52大事件
2020/03/03 欧美动漫
PHP获取一个字符串中间一部分字符的方法
2014/08/19 PHP
php通过记录IP来防止表单重复提交方法分析
2014/12/16 PHP
yepnope.js 异步加载资源文件
2011/09/08 Javascript
JavaScript之Getters和Setters 平台支持等详细介绍
2012/12/07 Javascript
用示例说明filter()与find()的用法以及children()与find()的区别分析
2013/04/26 Javascript
js对图片base64编码字符串进行解码并输出图像示例
2014/03/17 Javascript
javascript判断是否按回车键并解决浏览器之间的差异
2014/05/13 Javascript
jquery插件unobtrusive实现片段式加载
2015/06/15 Javascript
一张Web前端的思维导图分享
2015/07/03 Javascript
javascript笔记之匿名函数和闭包
2017/02/06 Javascript
webpack独立打包和缓存处理详解
2017/04/03 Javascript
详谈AngularJs 控制器、数据绑定、作用域
2017/07/09 Javascript
js使用原型对象(prototype)需要注意的地方
2017/08/28 Javascript
vue实现样式之间的切换及vue动态样式的实现方法
2017/12/19 Javascript
vue使用ElementUI时导航栏默认展开功能的实现
2018/07/04 Javascript
Angular6 正则表达式允许输入部分中文字符
2018/09/10 Javascript
Vue动态加载异步组件的方法
2018/11/21 Javascript
原生js实现trigger方法示例代码
2019/05/22 Javascript
vuex存储token示例
2019/11/11 Javascript
vue+vuex+axios从后台获取数据存入vuex,组件之间共享数据操作
2020/07/31 Javascript
Python从MP3文件获取id3的方法
2015/06/15 Python
Python 装饰器深入理解
2017/03/16 Python
python创建文件时去掉非法字符的方法
2018/10/31 Python
在Python中构建增广矩阵的实现方法
2019/07/01 Python
python中列表的切片与修改知识点总结
2019/07/23 Python
python判断单向链表是否包括环,若包含则计算环入口的节点实例分析
2019/10/23 Python
Python特殊属性property原理及使用方法解析
2020/10/09 Python
发现世界上最好的珠宝设计师:JewelStreet
2017/12/17 全球购物
事假请假条范文
2014/04/11 职场文书
通知函的格式
2015/04/27 职场文书
在HTML5 localStorage中存储对象的示例代码
2021/04/21 Javascript
详解解Django 多对多表关系的三种创建方式
2021/08/23 Python
关于Mybatis中SQL节点的深入解析
2022/03/19 Java/Android
在Centos 8.0中安装Redis服务器的教程详解
2022/03/21 Redis
JS实现页面炫酷的时钟特效示例
2022/08/14 Javascript