對Python裝飾器的個人理解方法

2021-09-03 09:30:27 字數 3184 閱讀 3259

0.說明

在自己好好總結並對python裝飾器的執行過程進行分解之前,對於裝飾器雖然理解它的基本工作方式,但對於存在複雜引數的裝飾器(裝飾器和函式本身都有引數),總是會感到很模糊,即使這會弄懂了,下一次也很快忘記,其實本質上還是沒有多花時間去搞懂其中的細節問題。

最近在對《python核心程式設計》做總結,收穫了不少,下面分享一下我自己對於python裝飾器的理解,後面還提供了乙個較為複雜的python裝飾器的執行過程的分解,可以參考一下。

1.python裝飾器的出現

在沒有裝飾器之前,如果要在類中定義乙個靜態方法,需要使用下面的方法:

class myclass(object):

def staticfoo():

staticfoo = staticmethod(staticfoo)

即要在該靜態方法中加入類似staticmethod()內建函式將該方法轉換為靜態方法,這顯然非常麻煩,而有了裝飾器之後,就可以寫成下面這樣:

class myclass(object):

@staticmethod

def staticfoo():

pass

這樣就簡潔很多了。

2.python裝飾器型別與理解

(1)無引數裝飾器

下面的情況:

@f

def foo():

pass

其實就相當於:

def foo():

pass

foo = g(foo)

下面的情況:

@g

@fdef foo():

pass

就相當於:

def foo():

pass

foo = g(f(foo))

(2)含引數裝飾器

下面的情況:

@decomaker(deco_args)

def foo():

pass

就相當於:

def foo():

pass

foo = decomaker(deco_args)(foo)

用這樣的思想去理解就非常好理解了:decomaker()用deco_args做了些事並返回函式物件,而該函式物件正是以foo作為其引數的裝飾器。

下面多個裝飾器的例子也是按這樣的思想去理解。

下面的情況:

@deco1(deco_arg)

@deco2()

def foo():

pass

就相當於:

def foo():

pass

foo = deco1(deco_arg)(deco2(foo))

3.python裝飾器執行過程的手動分解

ok,有了上面的理論基礎,理解下面乙個較為複雜的裝飾器就很容易了:

from functools import wraps

def log(text):

def decorator(func):

@wraps(func)                    #it works like:wraper.__name__ = func.__name__

print '%s %s():' % (text, func.__name__)

return func(*args, **kwargs)

return decorator

@log('hello')

def now(area):

print area, '2016-01-23'

now('beijing')

print 'the name of function now() is:', now.__name__

執行如下:

/usr/bin/python2.7 /home/xpleaf/pycharmprojects/decorator_test/dec10.py

hello now():

beijing 2016-01-23

the name of function now() is: now

對於該程式的執行過程,可以分析如下:

1.先執行log('hello')函式,此時返回了乙個新的函式,只不過其中的text變數被替換為'hello',所以用來裝飾now函式的新的裝飾器如下:

def decorator(func):

@wraps(func)                    #it works like:wraper.__name__ = func.__name__

print '%s %s():' % ('hello', func.__name__)

return func(*args, **kwargs)

2.所以此時的now函式,就相當於:

now = decorator(now)
3.即now就相當於:

def now(*args, **kwargs):

print '%s %s():' % ('hello', old_now.__name__)

return old_now(*args, **kwargs)

所以,輸出的結果也就非常好理解了。

關於wraps,它也是乙個裝飾器,使用它的作用是,被我們用自定義裝飾器修改後的函式,它的函式名稱,即func.__name__跟原來是一樣的,而它的工作原理正如上面所提及的,即:

wraper.__name__ = func.__name__
也就是說,使用wraps可以不改變原來函式的屬性,當然,上面只是簡單說明了一下其工作原理,詳細的可以參考wraps的源**。

在github上給出了10個理解裝飾器的例子,可以參考一下:

本文選中我的《python回顧與整理》系列博文中的《python回顧與整理9:函式和函式式程式設計》

對Python裝飾器的個人理解

首先,裝飾器的的返回值是接力棒。被當做引數的函式作為返回值返回到裝飾器的內部函式,然後裝飾器返回值是內部函式,即最終裝飾器的返回值是當做引數的函式。列子 def square it func def new function args,kwargs result func args,kwargs s...

python裝飾器理解 python裝飾器理解

裝飾器 在不改變原函式的 和呼叫方法的基礎上,給原函式增加額外的功能 理解宣告 為了方便理解,以下例子採用最簡潔的函式和新增的功能 給原函式新增乙個執行時間 import time def timer func def inner func return inner timer func timer...

python裝飾器 理解Python裝飾器

在python中,對於乙個函式,若想在其執行前後做點什麼,那麼裝飾器是再好不過的選擇,話不多說,上 usr bin env coding utf 8 script 01.py author howie from functools import wraps def decorator func wr...