裝飾器decorator
裝飾器,在設計模式中有一種模式叫做裝飾器模式,雖說不完全是設計模式中的那個,
但是其思路是一致的。目的都是需要添加功能,但是又不希望更改原來的代碼。
比如我已經有一個函數do_something()
,然後我希望添加一些功能,但是又不應該
直接去更改這個函數的代碼,我們就可以通過裝飾器的方式,在前後進行添加,並且
將這個函數包裹起來。由於python的函數式特性,我們可以很輕鬆的做到這一點,
因爲其函數是first class的,也就是說函數可以作爲參數等傳遞。
其實這個概念是非常簡單的,如果說有一些麻煩的地方就是python的裝飾器語法,裝飾器
語法其實只是一個語法糖,不過因爲這個語法糖使得裝飾器不那麼直觀了(但是要是沒有
裝飾器語法,我們也就不需要把裝飾器拿出來說啦)
函數作爲參數
在python中,函數可以作爲參數進行傳遞:
def call_a_func(func):
func()
def hello():
print("hello")
call_a_func(hello)
這裏我們將hello傳入了call_a_func
函數,這個函數將傳入的參數進行調用,也就是其
接收的參數是一個函數,而他調用了這個函數,相信這個例子足以讓人理解函數作爲參數了。
裝飾器語法
裝飾器語法,形式爲:
@decorator
def hello():
pass
這裏的decorator是裝飾器的名字,也就是另外一個函數,hello是一個函數。
注意,這裏的@decorator 相當於 hello = decorator(hello)
其實這句話纔是我寫這個博客的重點,因爲只要記住這個用法,別的講解都不需要了。
裝飾器,相當於將原函數作爲參數,然後將裝飾器的返回結果代替原函數,有了這個結果,
我們其實就可以隨心所欲使用裝飾器了。
在實際使用當中,有一些技巧,比如:
def deco(func):
def _deco():
print("pre")
func()
print("post")
return _deco
@deco
def hello():
pass
這裏我們相當於使用了hello = deco(hello)
,最後使得新的hello爲deco內部定義的_deco函數,
這個函數調用了原hello並且在前後增加了功能,爲什麼不直接在前後做一些功能然後返回原來
的hello呢?這是因爲這樣的效果只完成一次,如果返回原hello,只在第一次調用deco的時候
會有前後添加功能的效果,等到deco返回之後,以後的調用就只使用了hello了。所以,裝飾器
並非每一次調用都會進入hello = deco(hello)
,而是隻進行一次