成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python開發中如何使用Hook技巧

新聞 后端
什么是Hook,就是在一個已有的方法上加入一些鉤子,使得在該方法執行前或執行后另在做一些額外的處理,那么Hook技巧有什么作用以及我們為什么需要使用它呢?

什么是Hook,就是在一個已有的方法上加入一些鉤子,使得在該方法執行前或執行后另在做一些額外的處理,那么Hook技巧有什么作用以及我們為什么需要使用它呢,事實上如果一個項目在設計架構時考慮的足夠充分,模塊抽象的足夠合理,設計之初為以后的擴展預留了足夠的接口,那么我們完全可以不需要Hook技巧。但恰恰架構人員在項目設計之初往往沒辦法想的足夠的深遠,使得后續在擴展時深圳面臨重構的痛苦,這時Hook技巧似乎可以為我們帶來一記緩兵之計,通過對舊的架構進行加鉤子來滿足新的擴展需求。

下面我們就來看看如果進行Hook處理,我們按照Hook的對象的層級來逐一介紹

對類進行Hook

也就是說我們得鉤子需要監控到類的創建等操作,然后在此之前或之后做我們希望的操作

1、Hook類的創建

你可以在寫一個類的時候為其添加__metaclass__屬性

class Foo(Bar): __metaclass__ = something…

Python創建類的過程是這樣的:

Foo中有__metaclass__這個屬性嗎?如果是,Python會在內存中通過__metaclass__創建一個名字為Foo的類。如果Python沒有找到__metaclass__,它會繼續在Bar(父類)中尋找__metaclass__屬性,并嘗試做和前面同樣的操作。如果Python在任何父類中都找不到__metaclass__,它就會在模塊層次中去尋找__metaclass__,并嘗試做同樣的操作。如果還是找不到__metaclass__,Python就會用內置的type來創建這個類對象。

所以我們需要在給__metaclass__屬性的值是一個能夠創建一個類的東西,即一個繼承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) :無論訪問存在還是不存在的屬性都先訪問該方法

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類屬性

python描述符是一個“綁定行為”的對象屬性,在描述符協議中,它可以通過方法重寫屬性的訪問。這些方法有 __get__(), __set__(), 和__delete__()。如果這些方法中的任何一個被定義在一個對象中,這個對象就是一個描述符。

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__() 方法,可能會導致無法調用描述符)

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)修飾不帶參數的方法

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

3)使用帶參數的修飾符來修飾方法

def something(a,b): def new_func(func):def wrap(*args,**kargv): print a func(*args,**kargv) print breturn wrap return new_func@something(1,2)def func(a,b): pass

其他Hook

1、Hook內建方法

#Hookopen方法real_open = __builtins__.open__builtin__.open = my_open#Hookimport方法real_importer = __import____builtins__.__import__ = my_importer

上述操作使得my_open代替了python內置的open方法,故而我們可以使用我們自己的my_open方法來監控后續對open方法的調用了

2、Monkey Patch

from SomeOtherProduct.SomeModule import SomeClassdef speak(self): return "ookookeeeeeeeee!"SomeClass.speak = speak

實際上這是所有語言都會使用到的Hook技巧,往往在我們使用了第三方的包,希望在之上做一些擴展,但又不想改動原有的代碼時使用

多說一句

上述提到了修飾符的操作,那么我們在使用修飾符時有一些小技巧需要了解

1、使用functools

防止使用修飾器后函數簽名被改變

from functools import wrapsdef my_dec(func): @wraps(func) def wrapped():print %siscalled%func.__name__return func() return wrapped@my_decdef foo(): pass

這樣處理后,foo方法的簽名與被修飾之前保持了一致,否則簽名將會變成my_dec方法的簽名

2、使用decorator模塊來做修飾器

from decorator import decorator@decoratordef wrap(f,*args,**kw): print start f(*args,**kw) print end#這樣wrap方法就變成了一個decorator@wrapdef func(): print func

3、使用類做修飾器

class test(object): def__init__(self,func): self._func = func def__call__(self): print start self._func() print end@testdef func(): print funcfunc()startfuncend

實際應用中很少遇到可以使用一個類作為修飾器,但實際上只要一個類實現了__call__方法,其就可以作為一個修飾器存在了,并且由于類的可操作性較方法更強大,所以類做修飾器也可以實現更豐富的特性。

小編就先聊到這里,今天交流的內容都是硬知識,普通的開發過程中也許并不能使用的上,但了解這些知識對于編程能力的提高很有幫助,也能夠幫助你更深入的理解Python的機制。

責任編輯:張燕妮 來源: 圖靈學院
相關推薦

2009-08-06 17:15:34

C#開發和使用

2010-02-06 13:46:55

Android開發

2011-08-08 17:05:02

XCode UserScript 腳本

2019-10-28 14:37:10

MySQL 數據庫收藏

2010-08-31 13:14:41

CSSoverflow

2012-04-26 13:26:58

iPhone應用技巧

2020-07-10 06:10:14

Python開發代碼

2023-03-09 15:10:49

應用開發鴻蒙

2010-02-03 10:45:33

2011-08-18 15:56:08

iPhone開發內存

2011-08-05 16:10:31

iPhone 網絡 NSURLConne

2011-04-06 15:51:32

DelphiHOOK

2024-07-16 09:51:39

HTMLHookReact

2020-02-21 08:00:00

Pythonasyncio編程語言

2015-07-27 09:36:09

storyboard

2014-08-04 17:46:15

NavBarTarBar

2009-12-03 13:47:13

Microsoft V

2009-02-25 16:03:31

WindowsExplorer進程

2010-11-18 16:18:23

EXECUTE IMM

2011-11-07 13:38:27

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费精品久久久久久中文字幕 | 国产精品美女久久久久久久久久久 | 国产精品永久免费视频 | 日韩视频在线观看中文字幕 | 久久aⅴ乱码一区二区三区 亚洲国产成人精品久久久国产成人一区 | 羞羞视频在线观看免费观看 | 亚洲欧洲精品在线 | 国产一二三区免费视频 | 日韩精品久久久 | 91精品国产高清久久久久久久久 | 亚洲一区二区三区在线视频 | 日韩精品 电影一区 亚洲 | 日本三级在线网站 | 欧美成视频 | 成人小视频在线观看 | 黄色av一区| 亚洲精选一区二区 | 精品一区二区在线观看 | 妞干网av| 一级无毛片 | 国产小视频自拍 | 国产成人精品综合 | 国产一级片免费看 | 精品国模一区二区三区欧美 | 日韩福利在线 | 久久国产精品一区二区三区 | h视频网站在线观看 | 久草免费在线视频 | 亚洲av一级毛片 | 国外成人在线视频网站 | 精品欧美一区二区三区久久久小说 | 成人不卡视频 | 7777精品伊人久久精品影视 | 精品国产一区二区久久 | 免费的日批视频 | 一二三四在线视频观看社区 | 欧美性受xxxx白人性爽 | 欧美伊人影院 | 亚州一区二区三区 | 亚洲精品自在在线观看 | 亚洲欧美视频 |