2017年架构师最重要的48个小时 | 8折倒计时
什么是Hook,就是在一个已有的办法上参加一些钩子,使得在该办法履行前或履行后另在做一些额外的处理,那么Hook技能有什么感化以及我们为什么须要应用它呢,事实上如不雅一个项目在设计架构时推敲的足够充分,模块抽象的足够合理,设计之初为今后的扩大预留了足够的接口,那么我们完全可以不须要Hook技能。但恰好架构人员在项目设计之初往往没办法想的足够的深远,使得后续在扩大时深圳面对重构的苦楚,这时Hook技能似乎可认为我们带来一记缓兵之计,经由过程对旧的架构进行加钩子来知足新的扩大需求。

下面我们就来看看如不雅进行Hook处理,我们按照Hook的对象的层级来一一介绍
2、应用decorator模块来做润饰器
也就是说我们得钩子须要监控到类的创建等操作,然后在此之前或之后做我们欲望的操作
1、Hook类的创建
你可以在写一个类的时刻为其添加__metaclass__属性
class Foo(Bar): __metaclass__ = something…
Python创建类的过程是如许的:
Foo中有__metaclass__这个属性吗?如不雅是,Python会在内存中经由过程__metaclass__创建一个名字为Foo的类。如不雅Python没有找到__metaclass__,它会持续在Bar(父类)中寻找__metaclass__属性,尝尝试做和前面同样的操作。如不雅Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,尝尝试做同样的操作。如不雅照样找不到__metaclass__,Python就会用内置的type来创建这个类对象。
比如:
class Singleton(type): def__init__(cls, name, bases, dict): super(Singleton, cls).__init__(name, bases, dict) cls._instance = None def__call__(cls, *args, **kw): if cls._instance is None: cls._instance = super(Singleton, cls).__call__(*args, **kw) return cls._instanceclass MyClass(object): __metaclass__ = Singleton
Singleton就是一个可以或许创建类的对象,因为它持续了type
也正因为此,我们可以在Singleton这个类中去监控MyClass的创建过程
2、Hook实例属性
这里我们须要操作的属性是__getattribute__和__getattr__
object.__getattribute__(self, name) :无论拜访存在照样不存在的属性都先拜访该办法
对类进行Hook
object.__getattr__(self, name) :当不存在__getattribute__办法或者激发了AttributeError异常时拜访该办法
class C(object): a = 'abc' def __getattribute__(self, *args, **kwargs): print(__getattribute__() is called) return object.__getattribute__(self, *args, **kwargs) def __getattr__(self, name): print(__getattr__() is called) return namec = C()print c.a__getattribute__() is calledabcprint c.aa__getattribute__() is called__getattr__() is calledaa
可以看到,拜访已有属性a时,__getattribute__被调用,拜访不决义的属性aa时__getattribute__先被调用,接着__getattr__被调用
3、Hook类属性
class Desc(object): def __get__(self, instance, owner):print(__get__...) def __set__(self, instance, value):print('__set__...')class TestDesc(object): x = Desc()t = TestDesc()t.x__get__...- self: Desc的实例对象,其实就是TestDesc的属性x
- instance: TestDesc的实例对象,其实就是t
- owner: 即谁拥有这些器械,当然是 TestDesc这个类,它是最高统治者,其他的一些都是包含在它的内部或者由它生出来的
为了让描述符可以或许正常工作,它们必须定义在类的层次上。不然Python无法主动为你调用__get__和__set__办法。
而根据之前对类办法的解释,引用t.x的时刻是否会先引用TestDesc的__getattribute__办法呢?谜底是会的,其实拜访属性时在python中真实的查找次序是如许的:
1)__getattribute__(), 无前提调用
2)数据描述符(定义了__set__或__delete__的描述符):由1)触发调用 (若工资的重载了该 __getattribute__() 办法,可能会导致无法调用描述符)
小编就先聊到这里,今天交换的内容都是硬常识,通俗的开辟过程中也许并不克不及应用的上,但懂得这些常识对于编程才能的进步很有赞助,也可以或许赞助你更深刻的懂得Python的机制。
所以我们须要在给__metaclass__属性的值是一个可以或许创建一个类的器械,即一个持续type的类。
3)实例对象的字典
4)类的字典
5)非数据描述符(只定义了__get__的描述符)
6)父类的字典
7)__getattr__() 办法
4、应用润饰符来Hook类
def singleton(cls, *args, **kw): instances = {} def _singleton(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return _singleton@singletonclass MyClass(object): a = 1 def __init__(self, x=0): self.x = x我们应用singleton办法把MyClass润饰为了一个单例模式,同时我们也在singleton办法中实现了对MyClass实例过程的监控。
对办法进行Hook
1、润饰符来Hook办法
1)润饰不带参数的办法
from SomeOtherProduct.SomeModule import SomeClassdef speak(self): return "ookookeeeeeeeee!"SomeClass.speak = speak
def something(func): def wrap(): print start func() print end return wrap@somethingdef func(): pass
2)润饰带参数的办法
def something(func): defwrap(*args,**kargv):print startfunc(*args,**kargv)print end return wrap@somethingdef func(a,b): pass
推荐阅读
2017年架构师最重要的48个小时 | 8折倒计时 因为互联网的蓬勃成长,科技技巧的赓续迭代更新,中国的互联网行业已经步入的世界的前列,因为,我们经常能看到,在各类各样的报道中,法度榜样>>>详细阅读
本文标题:Python开发中如何使用Hook技巧
地址:http://www.17bianji.com/lsqh/38335.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示