先定義乙個簡單的函式:
def sum(x, y):
print(' x + y', eval('x + y'), sep=' = ')
sum(37, 73)
# 執行結果
# x + y = 110
現在我們假設想要增加上面函式的功能,比如對函式做乙個簡單的說明,但又不希望修改這個求和函式的定義。此時就需要用到裝飾器(decorator)了。
所謂裝飾器,就是在**執行期間動態增加功能的一種方式,它的本質就是乙個返回函式的高階函式。下面具體給出乙個示例:
def description(func):
def des(*args, **kw_args):
print('{} is a sum function:'.format(func.__name__))
return func(*args, **kw_args)
return des
@description
def sum(x, y):
print(' x + y', eval('x + y'), sep=' = ')
sum(73, 37)
# 執行結果
# sum is a sum function:
# x + y = 110
description函式是乙個decorator,所以它接受乙個函式作為引數,並返回乙個函式。
把@description放到sum()函式的定義處,相當於執行了語句:sum = description(sum)
。對於上述**的解釋:首先,由於description()是乙個裝飾器,返回乙個函式,所以原始的sum()函式仍然存在,只是同名的sum變數指向了乙個新的函式,於是呼叫sum(37, 73)將執行新函式即在description()函式中返回的des()函式。在des()函式內,首先對原始函式的說明資訊,然後呼叫原始函式。
如果decorator本身需要傳入引數,那就需要編寫乙個返回decorator的高階函式。例如,我們現在想自定義對函式的說明資訊,而不是由系統指定:
def description(information):
def des_decorator(func):
def des(*args, **kw_args):
print('%s: %s' % (func.__name__, information))
return func(*args, **kw_args)
return des
return des_decorator
@description('a sum function:')
def sum(x, y):
print(' x + y', eval('x + y'), sep=' = ')
print(sum.__name__)
sum(73, 37)
# 執行結果
# des
# sum: a sum function
# x + y = 110
上述**呼叫sum(73, 37)時的情況是這樣的:sum = description('a sum function')(sum)。先執行description('a sum function'),返回的是乙個decorator,再呼叫返回的函式並傳入引數sum()函式,返回值為des()函式。在des()函式內,首先對原始函式的說明資訊,然後呼叫原始函式。
當前存在的問題:我們已在**中說明,經過裝飾器修飾後的sum()函式,sum.__name變為了des,因此我們需要對此進行修改。將原始函式達的__name__等屬性複製到des()函式中,否則,有些依賴於函式簽名的**段就會出現意想不到的錯誤:
import functools
def description(func):
@functools.wraps(func)
def des(*args, **kw_args):
print('{} is a sum function:'.format(func.__name__))
return func(*args, **kw_args)
return des
對部分**做如上修改即可。
示例:請編寫乙個decorator,能在函式呼叫的前後列印出'begin call'和'end call'的日誌。
再思考一下能否寫出decorator,使它既支援:
@multi_decorator
def f():
pass
又支援:
@multi_decorator('information')
def f():
pass
import functools
def multi_decorator(*t_args):
def m_decorator(func):
@functools.wraps(func)
def dec(*args, **kw_args):
if len(t_args) > 0:
print('%s' % t_args[0])
else:
print('begin call')
func(*args, **kw_args)
print('end call')
return dec
return m_decorator
@multi_decorator()
def sum(x, y):
print('x + y = %d' % (x + y))
@multi_decorator('execute the function')
def sum2(x, y):
print('x + y = %d' % (x + y))
sum(73, 37)
print("------- ------- -------")
sum2(73, 37)
# 執行結果
# begin call
# x + y = 110
# end call
# ------- ------- -------
# execute the function
# x + y = 110
# end call
python基礎高階之裝飾器
一 閉包 1 閉包概念 def fn num 閉包的基本格式 def fn in print s num return fn in ret fn 30 ret 以上,ret fn 30 做了一下幾件事情 1,讓fn in指向某個記憶體空間 函式 2,在這個空間中建立乙個num指向30 3,把fn i...
python 裝飾(高階函式)
python 裝飾 高階函式 高階函式 1 把乙個函式名當做實參傳給另外乙個函式 在不修改被裝飾函式源 2 返回值 中包含函式名 高階函式實現1的功能 def bar print in the bar deftest1 func print in the test1 print func func ...
python基礎 裝飾器高階
在之前的部落格中裝飾器初識 了解了函式閉包 裝飾器,這篇筆記來繼續了解下裝飾器的高階用法 我們先來看乙個通用的裝飾器寫法 def func definner args,kwargs print before ret func args,kwargs print after return ret re...