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将多个excel表格合并为一个表格
Feb 22 Python
Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例
Jul 27 Python
使用python将多个excel文件合并到同一个文件的方法
Jul 09 Python
用Python爬取QQ音乐评论并制成词云图的实例
Aug 24 Python
pandas数据处理进阶详解
Oct 11 Python
利用Python自动化操作AutoCAD的实现
Apr 01 Python
Python Json数据文件操作原理解析
May 09 Python
使用keras实现densenet和Xception的模型融合
May 23 Python
python打开文件的方式有哪些
Jun 29 Python
Python 解析xml文件的示例
Sep 29 Python
浅谈anaconda python 版本对应关系
Oct 07 Python
利用 Python 的 Pandas和 NumPy 库来清理数据
Apr 13 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文件上传判断file是否己选择上传文件的方法
2014/11/10 PHP
PHP浮点数精度问题汇总
2015/05/13 PHP
ThinkPHP中使用Ueditor富文本编辑器
2015/09/02 PHP
php 输出json及显示json中的中文汉字详解及实例
2016/11/09 PHP
php版阿里云OSS图片上传类详解
2016/12/01 PHP
一个对于js this关键字的问题
2007/01/09 Javascript
xml分页+ajax请求数据源+dom取结果实例代码
2008/10/31 Javascript
jquery插件jbox使用iframe关闭问题
2009/02/09 Javascript
extjs render 用法介绍
2013/09/11 Javascript
完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
2014/12/17 Javascript
JS中创建函数的三种方式及区别
2016/03/13 Javascript
JS实现PC手机端和嵌入式滑动拼图验证码三种效果
2017/02/15 Javascript
Bootstrap风格的zTree右键菜单
2017/02/17 Javascript
ExtJs异步无法向外传值和赋值的完美解决办法
2017/06/14 Javascript
详解如何将 Vue-cli 改造成支持多页面的 history 模式
2017/11/20 Javascript
vue通过style或者class改变样式的实例代码
2018/10/30 Javascript
Vuex的初探与实战小结
2018/11/26 Javascript
JS获取表格视图所选行号的ids过程解析
2020/02/21 Javascript
vue3.0 的 Composition API 的使用示例
2020/10/26 Javascript
[01:01:31]2018DOTA2亚洲邀请赛3月29日小组赛B组 Mineski VS paiN
2018/03/30 DOTA
使用Python编写一个在Linux下实现截图分享的脚本的教程
2015/04/24 Python
Python判断字符串与大小写转换
2015/06/08 Python
Python用UUID库生成唯一ID的方法示例
2016/12/15 Python
使用python打印十行杨辉三角过程详解
2019/07/10 Python
Python Gluon参数和模块命名操作教程
2019/12/18 Python
150行python代码实现贪吃蛇游戏
2020/04/24 Python
在python中使用pyspark读写Hive数据操作
2020/06/06 Python
整理HTML5中支持的URL编码与字符编码
2016/02/23 HTML / CSS
记一次高分屏下canvas模糊问题
2020/02/17 HTML / CSS
印尼在线精品店:Berrybenka.com
2016/10/22 全球购物
关爱留守儿童倡议书
2014/04/15 职场文书
《菜园里》教学反思
2014/04/17 职场文书
幼儿园大班区域活动总结
2014/07/09 职场文书
毕业生实习证明
2014/09/19 职场文书
公司地址变更通知
2015/04/25 职场文书
使用ORM新增数据在Mysql中的操作步骤
2021/07/26 MySQL