標籤:span 替換 臨時對象 fun 順序 cal 需要 name python
1. 裝飾器
- 一種文法格式,用於替換另外一個編碼風格,一種文法糖,通過文法結構明確標識出這樣一種文法。
- 自動在被裝飾對象尾部執行代碼(不使用裝飾器文法時,需要明確寫明的代碼)
- 被裝飾對象可以為函數、類,被裝飾對象為函數(則定義裝飾器為函數裝飾器),被裝飾對象為類(則定義裝飾器為類裝飾器)
- 裝飾器自身可以是函數、類。
2. 函數裝飾器函數裝飾器自動添加的代碼:
+----------------------------+----------------------------+| @decorator | def func(): || def func(): | .... || .... | func = decorator(func) |+----------------------------+----------------------------+| func() | decorator(func)() |+----------------------------+----------------------------+
2.1. 裝飾器實現2.1.1. 函數方式實現
def decorator(F): def tmp_F(*args_for_F): 這個函數內可以添加任你想執行的代碼。 F(*args_for_F) return tmp_F # 這個返回的是函數地址
2.1.2. 類方式實現
class decorator: def __init__(self, F): self.__func = F def __call__(self, *args_for_F): self.__func(*args_for_F)* 注意:這個方式,被裝飾對象如果是類中的函數,則不能正常工作,self的含義發生了變化。
3. 類裝飾器類裝飾器自動添加的代碼:
+----------------------------+----------------------------+| @decorator | class C: || class C: | .... || .... | C = decorator(C) |+----------------------------+----------------------------+| C() | decorator(C)() |+----------------------------+----------------------------+
3.1. 裝飾器實現3.1.1. 函數方式實現
def decorator(cls): class tmp_C: def __init__(self, *args): # cls(*args) --> 走的是被裝飾類的建立物件流程程,然後把返回的對象 # 存放在裝飾器類執行個體對象的一個靜態屬性中。 self.__instance = cls(*args) # 最終訪問的是裝飾器類返回的執行個體,這個執行個體的屬性與被裝飾類執行個體的屬性是 # 一樣的。實現方法就是:屬性的傳遞。 def __getattr__(self, name): return getattr(self.__instance, name) return tmp_C@decoratorclass Person def __init__(self, name, sex): self.name = name self.sex = sex # 末尾自動加上代碼:Person = decorator(Person)x = Person(‘Tim‘, ‘Male‘) # x = Person(‘Tim‘, ‘Male‘) ---> Person已經
# 相當於tmp_C了,調用的是tmp_C.__init__print(x.name) # 調用的是 getattr(Person對象, name), 返回的是:‘Tim‘
3.1.2. 類方式實現
各種實現都存在缺點,推薦使用函數方式。類方式主要特點是考慮,__init__ 會被decorator()調用,對象調用,obj(),會調用decorator.__call__方法。
4. 裝飾器嵌套
+-------------------------+-------------------------+| @A | || @B | || @C | fc = C(my_func) || def my_func(..): | fb = B(fc) || ... | fa = A(fb) |+-------------------------+-------------------------+| @A | || @B | || @C | cc = C(MyClass) || class MyClass: | bc = B(cc) || ... | ac = A(bc) |+-------------------------+-------------------------+
5. 裝飾器參數
+----------------------------+----------------------------+| @decorator(A,B) | def func(): || def func(): | .... || .... | f1 = decorator(A,B) || | func = f1(func) |+----------------------------+----------------------------+| func() | decorator(A,B)(func)() |+----------------------------+----------------------------+def decorator(A,B): def f1(func): def f2(*args_for_func): ... return f2 return f1
6. 總結裝飾器的核心:通過文法結構,隱藏在被裝飾函數之後,需要插入一段固定代碼的方法。
- 不帶參數的裝飾器:被裝飾對象同名對象 = 裝飾器(被裝飾對象),運行時順序:執行裝飾器內函數 -> 被裝飾函數
- 帶參數的裝飾器:
- 被裝飾對象同名對象 = ( 裝飾器(裝飾器參數) )(被裝飾對象)
- == 等價於 ==
- 臨時對象 = 裝飾器(裝飾器參數) # 會執行裝飾器函數,返回中間函數
- 被裝飾對象同名對象 = 臨時對象( 被裝飾對象 ) # 會執行裝飾器內部的函數,並返回最底層一級封裝函數
- 嵌套裝飾器:
- 被裝飾對象同名對象 = ( 最外層裝飾器( 中間裝飾器... ( 最內層裝飾器 ( 被裝飾對象 ) ) )
- == 等價於 ==
- 最內層裝飾後臨時對象 = 最內層裝飾器 ( 被裝飾對象 ) # 會執行裝飾器函數,並返回封裝函數
- 中間裝飾後臨時對象 = 中間裝飾器 ( 最內層裝飾後臨時對象 ) # 會執行裝飾器函數,並返回封裝函數
- 被裝飾對象同名對象 = 最外層裝飾器 ( 中間裝飾後臨時對象 ) # 會執行裝飾器函數,並返回封裝函數
- 運行時順序:最外側 -> 中介層 -> 最內層 -> 被裝飾函數
[TimLinux] Python 裝飾器