python装饰器两层和三层_python装饰器为什么要双层嵌套函数

如同上面好幾位大大所說, 裝飾器 (@語法) 的作用:

@foo

def bar():

...

等價於:

bar = foo(bar)

翻成中文就是:

利用被 @ 的 function 當作引數來呼叫 @ function, 並且賦值給 被 @ function 的函數名

因為這個動作很像是 裝飾(修改, 擴增, 調整, 限制...) 原本的 bar, 所以被叫做 裝飾器:

By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.

雖然說是裝飾, 但執行完的 bar 跟原本的 bar 早已不是同一個人了, foo 會返回一個全新的對象, 通常是一個 function, 但很有可能返回的東西根本連 function 都不是:

def foo(func):

return None

@foo

def bar():

...

在上面的例子中, foo 變成了一個很奇怪的裝飾器, 因為他返還的東西是 None, 不但沒有裝飾, 還毀滅了 function

回到你一開始舉的例子:

def foo(func):

print('foo')

func()

@foo

def func_a():

print('func_a')

func_a()

你的 foo 沒有 return 述句, 這代表 foo 會返還 None, 你寫的根本是個毀滅器(開玩笑), 你看到的效果只是曇花一現的假象, 那是因為在 @ 語法發揮作用的那一瞬間, print 語法被執行了

但是你大可以試著調用 func_a, 你會發現錯誤被引發了, 因為 func_a 根本不是一個 function, 當然你想要達到的效果也無法復用

裝飾器的確不一定要使用 local function 或是嵌套式的函數, 但是我們通常都會讓裝飾器返還一個 function, 我覺得這是很重要的一點, 畢竟我們都會直覺認為被裝飾過的函數還是個函數

裝飾器的樣貌千千萬萬種, 有的的確使用單層嵌套就可以了, 比如說註冊函數:

registry = []

def register(func):

print('register {}'.format(func))

registry.append(func)

return func # 還是應該要 return func

原因是這個動作只需要在裝飾的時候處理一次即可, 你不會想要每次調用函數都註冊一次, 我們需要的只是原來的 function.

但是像 打印 log 或是 計算時間 等等的行爲, 我們還是得用嵌套的手法, 因為我們每次調用 function 都想要打印和計算, 我們需要的是一個新的 function, 這個 function 就靠 local function 製造出來, 那必然會產生層疊和嵌套, 還有一些比較複雜的帶參數的裝飾器, 可能會使用到超過兩層嵌套

小結

要不要嵌套要看目的, 但務必記得裝飾後返回函數

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值