jia*_*lai 10 python recursion decorator
我很难理解装饰递归函数的工作原理.对于以下代码段:
def dec(f):
def wrapper(*argv):
print(argv, 'Decorated!')
return(f(*argv))
return(wrapper)
def f(n):
print(n, 'Original!')
if n == 1: return(1)
else: return(f(n - 1) + n)
print(f(5))
print
dec_f = dec(f)
print(dec_f(5))
print
f = dec(f)
print(f(5))
Run Code Online (Sandbox Code Playgroud)
输出是:
(5, 'Original!')
(4, 'Original!')
(3, 'Original!')
(2, 'Original!')
(1, 'Original!')
15
((5,), 'Decorated!')
(5, 'Original!')
(4, 'Original!')
(3, 'Original!')
(2, 'Original!')
(1, 'Original!')
15
((5,), 'Decorated!')
(5, 'Original!')
((4,), 'Decorated!')
(4, 'Original!')
((3,), 'Decorated!')
(3, 'Original!')
((2,), 'Decorated!')
(2, 'Original!')
((1,), 'Decorated!')
(1, 'Original!')
15
Run Code Online (Sandbox Code Playgroud)
第一个打印f(n),因此每当f(n)被递归调用时,它自然会打印'Original'.
第二个打印def_f(n),所以当n传递给包装器时,它会递归调用f(n).但是包装器本身不是递归的,因此只打印一个"装饰".
第三个让我困惑,这与使用装饰器@dec相同.为什么装饰f(n)也会调用包装器五次?在我看来,def_f = dec(f)和f = dec(f)只是绑定到两个相同函数对象的两个关键字.当装饰函数与未修饰函数同名时,还有其他事情发生吗?
谢谢!
Python中的所有赋值都只是将名称绑定到对象.当你有
f = dec(f)
Run Code Online (Sandbox Code Playgroud)
你正在做的是将名称绑定f到返回值dec(f).此时,f不再指原始功能.原始函数仍然存在并由new调用f,但您不再具有对原始函数的命名引用.
正如你所说,第一个像往常一样被召唤.
第二个在全局范围内放置一个名为dec_f的f的装饰版本.调用Dec_f,因此打印"Decorative!",但在传递给dec的f函数内部,你调用f本身,而不是dec_f.查找名称f并在全局范围内找到它,它仍然在没有包装器的情况下定义,所以从而只有f被调用.
在3re示例中,您将装饰版本分配给名称f,因此当在函数f内部时,查找名称f,它在全局范围内查找,找到f,现在是装饰版本.
| 归档时间: |
|
| 查看次数: |
4104 次 |
| 最近记录: |