关于装饰器的应用
课后作业第46题动手题第0题import time
def delay(func):
def funa():
time.sleep(1)
func()
return funa
def fib():
back1, back2 = 0, 1
@delay
def func():
nonlocal back1, back2
back1, back2 = back2, back1 + back2
print(back1, end=' ')
return func
def get_fib(n):
f = fib()
for i in range(n):
f()
n = int(input("请输入需要获取的斐波那契数:"))
get_fib(n)
这段代码中,为什么不能将修饰器放到函数fib上面??
import time
def delay(func):
def funa():
time.sleep(1)
func()
return funa
@delay
def fib():
back1, back2 = 0, 1
def func():
nonlocal back1, back2
back1, back2 = back2, back1 + back2
print(back1, end=' ')
return func
def get_fib(n):
f = fib()
for i in range(n):
f()
n = int(input("请输入需要获取的斐波那契数:"))
get_fib(n)
装饰器的作用是在不改变被修饰函数代码的前提下,为函数添加额外的功能。在第一段代码中,将装饰器放在了内部函数func上面,这样每次调用func时都会执行装饰器的功能,即延迟1秒钟。而将装饰器放在函数fib上面,则说明每次调用fib时都会执行装饰器的功能。但是由于装饰器中使用了内层函数func,而这个函数在装饰器外部并没有定义,所以会报错。
你可以把装饰器放在函数外部,然后再在函数上面使用装饰器。修改后的代码如下:
import time
def delay(func):
def funa():
time.sleep(1)
func()
return funa
@delay
def fib():
back1, back2 = 0, 1
def func():
nonlocal back1, back2
back1, back2 = back2, back1 + back2
print(back1, end=' ')
return func
def get_fib(n):
f = fib()
for i in range(n):
f()
n = int(input("请输入需要获取的斐波那契数:"))
get_fib(n)
现在,每次调用fib函数时,都会先执行delay装饰器中的代码,延迟1秒钟,然后再执行函数fib中的代码。这样就实现了给fib函数添加延迟执行的功能。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 本帖最后由 jackz007 于 2024-5-3 22:25 编辑
这两句:
@delay
def func():
把函数 func() 作为 delay() 的被装饰对象;
def fib():
. . . . . .
def func():
. . . . .
return func
fib() 返回的是其内置函数 func() 的调用句柄,那么,下面这一句:
f = fib()
就会获得对 fib() 内置函数 func() 的调用句柄,下面的语句:
f()
就是在调用 fib() 的内置函数 func()
根据装饰器的运行机制,delay() 装饰了 func(),当每次通过 f() 调用 func() 的时候,会把调用转向到 delay(),并由 delay() 来完成对 func() 的实际调用。这样,每次调用 f() 都会经历由 delay() 产生的时间延迟。
如果改让 delay() 装饰 fib(),那么,在调用 fib() 的时候,会转向到调用 delay(),再由 delay() 来完成对 fib() 的实际调用,所以,只有执行这一句的时候会产生一次时间的延迟:
f = fib()
而在后面循环中多次调用的 f() 的时候,会直接调用未经 delay() 装饰的 func(),因而期间也不会产生任何延迟。
此外,用 delay() 装饰 fib() 还有一个问题:
def delay(func):
def funa():
time.sleep(1)
func() # <--- 问题语句:函数 funa() 实际完成对被装饰函数的调用,却没有传递函数的返回值。
return funa
调用 fib() 会返回其内置函数 func() 的调用句柄,如果用 delay() 装饰了 fib(),则会因为 funa() 无返回值,从而使这一句:
f = fib()
将无法取得 func() 的调用句柄,f 的值将会使 None,从而会使后续的 f() 语句非法。
如果想让delay() 装饰 fib(),则必须修改 delay()
def delay(func):
def funa():
time.sleep(1)
return func() # 修改这里
return funa
页:
[1]