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 相关文章推荐
10款最好的Web开发的 Python 框架
Mar 18 Python
Python下使用Scrapy爬取网页内容的实例
May 21 Python
浅谈Series和DataFrame中的sort_index方法
Jun 07 Python
python3+opencv3识别图片中的物体并截取的方法
Dec 05 Python
详解python 爬取12306验证码
May 10 Python
python之拟合的实现
Jul 19 Python
python 使用socket传输图片视频等文件的实现方式
Aug 07 Python
python3的数据类型及数据类型转换实例详解
Aug 20 Python
使用 Python 清理收藏夹里已失效的网站
Dec 03 Python
Python 通过正则表达式快速获取电影的下载地址
Aug 17 Python
10个python爬虫入门基础代码实例 + 1个简单的python爬虫完整实例
Dec 16 Python
python中if嵌套命令实例讲解
Feb 25 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
输出控制类
2006/10/09 PHP
php session 检测和注销
2009/03/16 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
Javascript var变量隐式声明方法
2009/10/19 Javascript
jQuery.Autocomplete实现自动完成功能(详解)
2010/07/13 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
js动态拼接正则表达式的两种方法
2014/03/04 Javascript
JavaScript 基本概念
2015/01/20 Javascript
jQuery实现数秒后自动提交form的方法
2015/03/05 Javascript
js实现模糊匹配功能
2017/02/15 Javascript
详解Vue使用命令行搭建单页面应用
2017/05/24 Javascript
详解Vuejs2.0 如何利用proxyTable实现跨域请求
2017/08/03 Javascript
说说AngularJS中的$parse和$eval的用法
2017/09/14 Javascript
node.js中axios使用心得总结
2017/11/29 Javascript
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
vue登录注册实例详解
2019/09/14 Javascript
基于Vue 撸一个指令实现拖拽功能
2019/10/09 Javascript
jQuery实现的解析本地 XML 文档操作示例
2020/04/30 jQuery
原生js+canvas实现下雪效果
2020/08/02 Javascript
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
在vue中封装方法以及多处引用该方法详解
2020/08/14 Javascript
vue实现路由懒加载的3种方法示例
2020/09/01 Javascript
Element-ui upload上传文件限制的解决方法
2021/01/22 Javascript
Python使用Windows API创建窗口示例【基于win32gui模块】
2018/05/09 Python
使用python 3实现发送邮件功能
2018/06/15 Python
15行Python代码实现网易云热门歌单实例教程
2019/03/10 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
python文字和unicode/ascll相互转换函数及简单加密解密实现代码
2019/08/12 Python
Python常用模块os.path之文件及路径操作方法
2019/12/03 Python
python爬取本站电子书信息并入库的实现代码
2020/01/20 Python
python 解决print数组/矩阵无法完整输出的问题
2020/02/19 Python
七一表彰活动方案
2014/01/18 职场文书
2014年售后服务工作总结
2014/11/18 职场文书
社区志愿者服务心得体会
2016/01/22 职场文书
煤矿施工安全协议书
2016/03/22 职场文书
SpringBoot整合minio快速入门教程(代码示例)
2022/04/03 Java/Android