1 回答

TA貢獻(xiàn)1993條經(jīng)驗 獲得超6個贊
提出的重復(fù)問題,python 裝飾器中的變量范圍 - 更改參數(shù)提供了有用的信息,解釋了為什么wrapper_repeat認(rèn)為nbrTimes是局部變量,以及如何nonlocal使用它來識別nbrTimes由repeat. 這將解決異常,但我認(rèn)為這不是您的情況的完整解決方案。您的裝飾功能仍然不會重復(fù)。
import functools
def repeat(nbrTimes=2):
'''
Define parametrized decorator with arguments
Default nbr of repeats is 2
'''
def real_repeat(func):
"""
Repeats execution 'nbrTimes' times
"""
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
nonlocal nbrTimes
while nbrTimes != 0:
nbrTimes -= 1
return func(*args, **kwargs)
return wrapper_repeat
return real_repeat
@repeat(2)
def display(x):
print("displaying:", x)
display("foo")
display("bar")
display("baz")
結(jié)果:
displaying: foo
displaying: bar
"foo" 和 "bar" 分別只顯示一次,而 "baz" 顯示零次。我認(rèn)為這不是理想的行為。
由于循環(huán)內(nèi)部,前兩個調(diào)用display無法重復(fù)。return 語句導(dǎo)致立即終止,并且不會發(fā)生進(jìn)一步的迭代。所以沒有裝飾功能會重復(fù)一次以上。一種可能的解決方案是刪除并調(diào)用該函數(shù)。return func(*args, **kwargs)whilewrapper_repeatwhilereturn
import functools
def repeat(nbrTimes=2):
'''
Define parametrized decorator with arguments
Default nbr of repeats is 2
'''
def real_repeat(func):
"""
Repeats execution 'nbrTimes' times
"""
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
nonlocal nbrTimes
while nbrTimes != 0:
nbrTimes -= 1
func(*args, **kwargs)
return wrapper_repeat
return real_repeat
@repeat(2)
def display(x):
print("displaying:", x)
display("foo")
display("bar")
display("baz")
結(jié)果:
displaying: foo
displaying: foo
“foo”被顯示了兩次,但現(xiàn)在“bar”和“baz”都沒有出現(xiàn)。這是因為nbrTimes在裝飾器的所有實例之間共享,這要歸功于nonlocal. 一旦display("foo")遞減nbrTimes到零,即使在調(diào)用完成后它也保持為零。display("bar")并將display("baz")執(zhí)行他們的裝飾器,看到它nbrTimes是零,并終止而不調(diào)用裝飾函數(shù)。
所以事實證明你不希望你的循環(huán)計數(shù)器是非本地的。但這意味著您不能nbrTimes用于此目的。嘗試根據(jù)nbrTimes' 值創(chuàng)建一個局部變量,然后將其遞減。
import functools
def repeat(nbrTimes=2):
'''
Define parametrized decorator with arguments
Default nbr of repeats is 2
'''
def real_repeat(func):
"""
Repeats execution 'nbrTimes' times
"""
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
times = nbrTimes
while times != 0:
times -= 1
func(*args, **kwargs)
return wrapper_repeat
return real_repeat
@repeat(2)
def display(x):
print("displaying:", x)
display("foo")
display("bar")
display("baz")
結(jié)果:
displaying: foo
displaying: foo
displaying: bar
displaying: bar
displaying: baz
displaying: baz
...當(dāng)您使用它時,您也可以使用for循環(huán)而不是while.
import functools
def repeat(nbrTimes=2):
'''
Define parametrized decorator with arguments
Default nbr of repeats is 2
'''
def real_repeat(func):
"""
Repeats execution 'nbrTimes' times
"""
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(nbrTimes):
func(*args, **kwargs)
return wrapper_repeat
return real_repeat
@repeat(2)
def display(x):
print("displaying:", x)
display("foo")
display("bar")
display("baz")
添加回答
舉報