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操作gmail实例
Jan 14 Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
Apr 05 Python
python操作excel的包(openpyxl、xlsxwriter)
Jun 11 Python
mvc框架打造笔记之wsgi协议的优缺点以及接口实现
Aug 01 Python
python如何制作英文字典
Jun 25 Python
使用APScheduler3.0.1 实现定时任务的方法
Jul 22 Python
Python递归及尾递归优化操作实例分析
Feb 01 Python
Python基于pandas绘制散点图矩阵代码实例
Jun 04 Python
浅谈Python里面None True False之间的区别
Jul 09 Python
深入了解NumPy 高级索引
Jul 24 Python
python获取时间戳的实现示例(10位和13位)
Sep 23 Python
用python对excel查重
Dec 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
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
2013/06/19 PHP
php实现ip白名单黑名单功能
2015/03/12 PHP
Laravel 实现关系模型取出需要的字段
2019/10/10 PHP
JavaScript中出现乱码的处理心得
2009/12/24 Javascript
深入理解JavaScript系列(7) S.O.L.I.D五大原则之开闭原则OCP
2012/01/15 Javascript
js内存泄露的几种情况详细探讨
2013/05/31 Javascript
JS常用字符串处理方法应用总结
2014/05/22 Javascript
jQuery 回调函数(callback)的使用和基础
2015/02/26 Javascript
深入理解JavaScript系列(19):求值策略(Evaluation strategy)详解
2015/03/05 Javascript
JavaScript仿微博发布信息案例
2016/11/16 Javascript
Ajax的概述与实现过程
2016/11/18 Javascript
vue.js学习之递归组件
2016/12/13 Javascript
angularJS之$http:与服务器交互示例
2017/03/17 Javascript
基于jQuery实现的单行公告活动轮播效果
2017/08/23 jQuery
vue实现弹框遮罩点击其他区域弹框关闭及v-if与v-show的区别介绍
2018/09/29 Javascript
JavaScript键盘事件响应顺序详解
2019/09/30 Javascript
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)
2020/01/14 Javascript
通过实例解析JavaScript常用排序算法
2020/09/02 Javascript
[46:00]Ti4 冒泡赛第二轮LGD vs C9 2
2014/07/14 DOTA
Python实现爬取知乎神回复简单爬虫代码分享
2015/01/04 Python
Python实现方便使用的级联进度信息实例
2015/05/05 Python
Python编程入门的一些基本知识
2015/05/13 Python
CentOS下使用yum安装python-pip失败的完美解决方法
2017/08/16 Python
numpy.transpose对三维数组的转置方法
2018/04/17 Python
深入理解Python异常处理的哲学
2019/02/01 Python
python设置随机种子实例讲解
2019/09/12 Python
详解Python yaml模块
2020/09/23 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
2021/03/03 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
一个C/C++编程面试题
2013/11/10 面试题
小学生考试获奖感言
2014/01/30 职场文书
办公设备采购方案
2014/03/16 职场文书
奥巴马胜选演讲稿
2014/05/15 职场文书
考察现实表现材料
2014/05/19 职场文书
党课心得体会范文
2014/09/09 职场文书
使用PDF.js渲染canvas实现预览pdf的效果示例
2021/04/17 Javascript