什么是Hook,就是在一個已有的方法上加入一些鉤子,使得在該方法執(zhí)行前或執(zhí)行后另在做一些額外的處理,那么Hook技巧有什么作用以及我們?yōu)槭裁葱枰褂盟兀聦嵣先绻粋€項目在設計架構時考慮的足夠充分,模塊抽象的足夠合理,設計之初為以后的擴展預留了足夠的接口,那么我們完全可以不需要Hook技巧。但恰恰架構人員在項目設計之初往往沒辦法想的足夠的深遠,使得后續(xù)在擴展時深圳面臨重構的痛苦,這時Hook技巧似乎可以為我們帶來一記緩兵之計,通過對舊的架構進行加鉤子來滿足新的擴展需求。
下面我們就來看看如果進行Hook處理,我們按照Hook的對象的層級來逐一介紹
對類進行Hook
也就是說我們得鉤子需要監(jiān)控到類的創(chuàng)建等操作,然后在此之前或之后做我們希望的操作
1、Hook類的創(chuàng)建
你可以在寫一個類的時候為其添加__metaclass__屬性
class Foo(Bar): __metaclass__ = something…
Python創(chuàng)建類的過程是這樣的:
Foo中有__metaclass__這個屬性嗎?如果是,Python會在內存中通過__metaclass__創(chuàng)建一個名字為Foo的類。如果Python沒有找到__metaclass__,它會繼續(xù)在Bar(父類)中尋找__metaclass__屬性,并嘗試做和前面同樣的操作。如果Python在任何父類中都找不到__metaclass__,它就會在模塊層次中去尋找__metaclass__,并嘗試做同樣的操作。如果還是找不到__metaclass__,Python就會用內置的type來創(chuàng)建這個類對象。
所以我們需要在給__metaclass__屬性的值是一個能夠創(chuàng)建一個類的東西,即一個繼承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就是一個能夠創(chuàng)建類的對象,因為它繼承了type
也正因為此,我們可以在Singleton這個類中去監(jiān)控MyClass的創(chuàng)建過程
2、Hook實例屬性
這里我們需要操作的屬性是__getattribute__和__getattr__
object.__getattribute__(self, name) :無論訪問存在還是不存在的屬性都先訪問該方法
object.__getattr__(self, name) :當不存在__getattribute__方法或者引發(fā)了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
新聞熱點
疑難解答