由於函式也是乙個物件,而且函式物件可能被賦值給變數,所以,通過變數也能呼叫該函式。
>>> def now():
... print('2018-4-11')
...>>> f = now
>>> f()
2018-4-11
>>>
函式物件有乙個__name__屬性,可以拿到函式的名字:>>> now.__name__
'now'
>>> f.__name__
'now'
現在,假設我們要增強now()函式的功能,比如,在函式呼叫前自動列印日誌,但又不希望修改now()函式的定義,這種在**執行期間動態增加功能的方式,稱之為「裝飾器」(decorator)。
本質上,decorator就是乙個返回函式的高階函式。所以我們要定義乙個能列印日誌的decorator,可以定義如下:
>>> def log(func):
... print('call %s():'%func.__name__)
... return func(*args,**kw)
...
觀察上面的log,因為它是乙個decorator,所以接受乙個函式作為引數,並返回乙個函式。我們要借助python的@語法,把decorator置於函式的定義處:
>>> @log
... def now():
... print('2018-4-11')
...
呼叫now()函式,不僅會執行now()函式本身,還會在執行now()函式前列印一行日誌:
>>> now()
call now():
2018-4-11
把@log放到now()函式定義處,相當於執行了語句:
now = log(now)
如果decorator本身需要傳入引數,那就需要編寫乙個返回decorator的高階函式,寫出來會更複雜。比如,要自定義log的文字:
def log(text):
def decorator(func):
print('%s%s():'%(text,func.__name__))
return func(*args,**kw)
return decorator
@log('execute')
def now():
print('2018-4-11')
now()
executenow():
2018-4-11
和兩層巢狀的decorator相比,3層巢狀的效果是這樣的:
>>> now = log('execute')(now)
>>> now.__name__
>>> import functools或是針對帶引數的decorator:>>> def log(func):
... @functools.wraps(func)
... print('call %s():'%fuc.__name__)
... return func(*args,**kw)
...
>>> import functools
>>> def log(text):
... def decorator(func):
... @functools.wraps(func)
... print('%s %s():'%(text,func.__name__))
... return func(*args,**kw)
... return decorator
...
Python 高階函式 裝飾器
裝飾器 定義裝飾器本身是乙個可呼叫物件,接收乙個函式作為引數,然後將其返回或替換成另乙個函式或可呼叫物件。可以理解成,原來那是一堵白牆,經過了一層裝飾,這層裝飾可能是漆也可能把牆掏空鑲進一層 變得金光閃閃,最後呈現在你眼前的就是裝飾後的樣子。可以把它完全當成常規函式來呼叫,其引數是另乙個函式。裝飾器...
Python函式 裝飾器高階
1.對擴充套件是開放的 為什麼要對擴充套件開放呢?我們說,任何乙個程式,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改。所以我們必須允許 擴充套件 新增新功能。2.對修改是封閉的 為什麼要對修改封閉呢?就像我們剛剛提到的,因為我們寫的乙個函式,很有可能已經交付給其他人使用了,如果這...
PYTHON高階函式和裝飾器
定義 裝飾器的本質是函式,用來裝飾其他的函式,為其他的函式新增功能。函式修飾符 用做函式的修飾符,可以在模組或者類的定義層內對函式進行修飾,出現在函式定義的前一行,不允許和函式定義在同一行乙個修飾符就是乙個函式,它將被修飾的函式作為引數,並返回修飾後的同名函式或其他可呼叫的東西 原則 1 不能修改被...