1. 程式人生 > 程式設計 >Python如何解除一個裝飾器

Python如何解除一個裝飾器

問題

一個裝飾器已經作用在一個函式上,你想撤銷它,直接訪問原始的未包裝的那個函式。

解決方案

假設裝飾器是通過 @wraps 來實現的,那麼你可以通過訪問 __wrapped__ 屬性來訪問原始函式:

>>> @somedecorator
>>> def add(x,y):
...   return x + y
...
>>> orig_add = add.__wrapped__
>>> orig_add(3,4)
7
>>>

討論

直接訪問未包裝的原始函式在除錯、內省和其他函式操作時是很有用的。 但是我們這裡的方案僅僅適用於在包裝器中正確使用了 @wraps

或者直接設定了 __wrapped__ 屬性的情況。

如果有多個包裝器,那麼訪問 __wrapped__ 屬性的行為是不可預知的,應該避免這樣做。 在Python3.3中,它會略過所有的包裝層,比如,假如你有如下的程式碼:

from functools import wraps

def decorator1(func):
  @wraps(func)
  def wrapper(*args,**kwargs):
    print('Decorator 1')
    return func(*args,**kwargs)
  return wrapper

def decorator2(func):
  @wraps(func)
  def wrapper(*args,**kwargs):
    print('Decorator 2')
    return func(*args,**kwargs)
  return wrapper

@decorator1
@decorator2
def add(x,y):
  return x + y

下面我們在Python3.3下測試:

>>> add(2,3)
Decorator 1
Decorator 2
5
>>> add.__wrapped__(2,3)
5
>>>

下面我們在Python3.4下測試:

>>> add(2,3)
Decorator 2
5
>>>

最後要說的是,並不是所有的裝飾器都使用了 @wraps ,因此這裡的方案並不全部適用。 特別的,內建的裝飾器 @staticmethod @classmethod 就沒有遵循這個約定 (它們把原始函式儲存在屬性 __func__

中)。

以上就是Python如何解除一個裝飾器的詳細內容,更多關於Python 解除裝飾器的資料請關注我們其它相關文章!