国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python裝飾器基礎概念與用法詳解

2020-01-04 13:44:50
字體:
來源:轉載
供稿:網友

本文實例講述了Python裝飾器基礎概念與用法。分享給大家供大家參考,具體如下:

裝飾器基礎

前面快速介紹了裝飾器的語法,在這里,我們將深入裝飾器內部工作機制,更詳細更系統地介紹裝飾器的內容,并學習自己編寫新的裝飾器的更多高級語法。

什么是裝飾器

裝飾是為函數和類指定管理代碼的一種方式。Python裝飾器以兩種形式呈現:

【1】函數裝飾器在函數定義的時候進行名稱重綁定,提供一個邏輯層來管理函數和方法或隨后對它們的調用。
【2】類裝飾器在類定義的時候進行名稱重綁定,提供一個邏輯層來管理類,或管理隨后調用它們所創建的實例。

簡而言之,裝飾器提供了一種方法,在函數和類定義語句的末尾插入自動運行的代碼——對于函數裝飾器,在def的末尾;對于類裝飾器,在class的末尾。這樣的代碼可以扮演不同的角色。

裝飾器提供了一些和代碼維護性和審美相關的有點。此外,作為結構化工具,裝飾器自然地促進了代碼封裝,這減少了冗余性并使得未來變得更容易。

函數裝飾器

通過在一個函數的def語句的末尾運行另一個函數,把最初的函數名重新綁定到結果。

用法

裝飾器在緊挨著定義一個函數或方法的def語句之前的一行編寫,并且它由@符號以及緊隨其后的對于元函數的一個引用組成——這是管理另一個函數的一個函數(或其他可調用對象)。

在編碼上,函數裝飾器自動將如下語法:

@decoratordef F(arg):  ...F(99)

映射為這個對等形式:

def F(arg):  ...F = decorator(F)F(99)

這里的裝飾器是一個單參數的可調用對象,它返回與F具有相同數目的參數的一個可調用對象。

當隨后調用F函數的時候,它自動調用裝飾器所返回的對象。

換句話說,裝飾實際把如下的第一行映射為第二行(盡管裝飾器只在裝飾的時候運行一次)

fun(6,7)decorator(func)(6,7)

這一自動名稱重綁定也解釋了之前介紹的靜態方法和property裝飾器語法的原因:

class C:  @staticmethod  def meth(...):...  @property  def name(self):...

實現

裝飾器自身是返回可調用對象的可調用對象。實際上,它可以是任意類型的可調用對象,并且返回任意類型的可調用對象:函數和類的任何組合都可以使用,盡管一些組合更適合于特定的背景。

有一種常用的編碼模式——裝飾器返回了一個包裝器,包裝器把最初的函數保持到一個封閉的作用域中:

def decorator(F):  def wrapper(*args):    # 使用 F 和 *args    # 調用原來的F(*args)  return wrapper@decoratordef func(x,y):  ...func(6,7)

當隨后調用名稱func的時候,它確實調用裝飾器所返回的包裝器函數;隨后包裝器函數可能運行最初的func,因為它在一個封閉的作用域中仍然可以使用。

為了對類做同樣的事情,我們可以重載調用操作:

class decorator:  def __init__(self,func):    self.func = func  def __call__(self,*args):    # 使用self.func和args    # self.func(*args)調用最初的func@decoratordef func(x,y):  ...func(6,7)

但是,要注意的是,基于類的代碼中,它對于攔截簡單函數有效,但當它應用于類方法函數時,并不很有效:

如下反例:

class decorator:  def __init__(self,func):    self.func = func  def __call__(self,*args):    # 調用self.func(*args)失敗,因為C實例參數無法傳遞class C:  @decorator  def method(self,x,y):    ...

這時候裝飾的方法重綁定到一個類的方法上,而不是一個簡單的函數,這一點帶來的問題是,當裝飾器的方法__call__隨后運行的時候,其中的self接受裝飾器類實例,并且類C的實例不會包含到一個*args中。

這時候,嵌套函數的替代方法工作得更好:

def decorator:  def warpper(*args):    # ...  return wrapper@decoratordef func(x,y):  ...func(6,7)class C:  @decorator  def method(self,x,y):    ...x = C()x.method(6,7)

類裝飾器

類裝飾器與函數裝飾器使用相同的語法和非常相似的編碼方式。類裝飾器是管理類的一種方式,或者用管理或擴展類所創建的實例的額外邏輯,來包裝實例構建調用。

用法

假設類裝飾器返回一個可調用對象的一個單參數的函數,類裝飾器的語法為:

@decoratorclass C:  ...x = C(99)

等同于下面的語法:

class C:  ...C = decorator(C)x = C(99)

直接效果是隨后調用類名會創建一個實例,該實例會觸發裝飾器所返回的可調用對象,而不是調用最初的類自身。

實現

類裝飾器返回的可調用對象,通常創建并返回最初的類的一個新的實例,以某種方式來擴展對其接口的管理。例如,下面的實例插入一個對象來攔截一個類實例的未定義的屬性:

def decorator(cls):  class Wrapper:    def __init__(self,*args):      self.wrapped = cls(*args)    def __getattr__(self,name):      return getattr(self.wrapped,name)  return Wrapper@decoratorclass C:        # C = decorator(C)  def __init__(self,x,y):    # Run by Wrapper.__init__    self.attr = 'spam'x = C(6,7)        # 等價于Wrapper(6,7)print(x.attr)

在這個例子中,裝飾器把類的名稱重新綁定到另一個類,這個類在一個封閉的作用域中保持了最初的類。

就像函數裝飾器一樣,類裝飾器通??梢跃帉憺橐粋€創建并返回可調用對象的“工廠”函數。

裝飾器嵌套

有時候,一個裝飾器不夠,裝飾器語法允許我們向一個裝飾器的函數或方法添加包裝器邏輯的多個層。這種形式的裝飾器的語法為:

@A@B@Cdef f(...):  ...

如下這樣轉換:

def f(...):  ...f = A(B(C(f)))

這里,最初的函數通過3個不同的裝飾器傳遞,每個裝飾器處理前一個結果。

裝飾器參數

函數裝飾器和類裝飾器都能接受參數,如下:

@decorator(A,B)def F(arg):  ...F(99)

自動映射到其對等形式:

def F(arg):  ...F = decorator(A,B)(F)F(99)

裝飾器參數在裝飾之前就解析了,并且它們通常用來保持狀態信息供隨后的調用使用。例如,這個例子中的裝飾器函數,可能采用如下形式:

def decorator(A,B):  # 保存或使用A和B  def actualDecorator(F):    # 保存或使用函數 F    # 返回一個可調用對象    return callable  return actualDecorator

以上,這是裝飾器的基礎知識,接下來將學習編寫自己的裝飾器

希望本文所述對大家Python程序設計有所幫助。


注:相關教程知識閱讀請移步到python教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 海兴县| 定襄县| 闸北区| 炎陵县| 高淳县| 盘山县| 香港| 定结县| 海南省| 理塘县| 阿拉善右旗| 中宁县| 芦山县| 富宁县| 商丘市| 虞城县| 吐鲁番市| 腾冲县| 榆中县| 灵武市| 三亚市| 滨州市| 遂平县| 浠水县| 建平县| 九寨沟县| 疏附县| 崇阳县| 罗江县| 西吉县| 湘潭县| 宁晋县| 东台市| 新绛县| 赣州市| 札达县| 临漳县| 双桥区| 阿巴嘎旗| 南阳市| 怀宁县|