在python中装饰递归函数

发布于 2021-01-29 18:02:59

我很难理解修饰的递归函数是如何工作的。对于以下代码段:

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))

输出为:

(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

第一个打印f(n),因此很自然,每次递归调用f(n)时,它都会打印“原始”。

第二个打印def_f(n),因此当n传递给包装器时,它将递归调用f(n)。但是包装器本身不是递归的,因此仅打印一个“装饰”。

第三个让我感到困惑,这与使用装饰器@dec相同。为什么修饰的f(n)也调用包装器五次?在我看来,def_f = dec(f)和f =
dec(f)仅仅是绑定到两个相同函数对象的两个关键字。装饰函数的名称与未装饰函数的名称相同时,还会发生其他情况吗?

谢谢!

关注者
0
被浏览
184
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    如您所说,第一个通常被称为。

    第二个在全局范围内放置f的修饰版本dec_f。调用Dec_f,以显示“
    Decorated!”,但在传递给dec的f函数内部,您调用f本身,而不是dec_f。在全局范围内查找并找到了名称f,在该名称中仍没有包装就对其进行了定义,因此从此以后,仅调用f。

    在3re示例中,您将修饰版本分配给名称f,因此在函数f中查找名称f时,它将在全局范围内查找,找到f,现在是修饰版本。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看