【问题标题】:Python dictionary setdefault() method used as a return value of a recursive functionPython 字典 setdefault() 方法用作递归函数的返回值
【发布时间】:2021-01-05 23:08:43
【问题描述】:

假设您想获得第 n 个斐波那契数。那么,一种可能性是使用递归函数

def Fib(n, d):
    """Assumes n is an int >= 0, d dictionary
    Returns nth Fibonacci number"""
    if n in d:
        return d[n]
    else:
        d[n] = Fib(n-1, d) + Fib(n-2, d)
        return d[n]

这很好用。我试图将其缩短为

 def Fib(n, d):
        return d.setdefault(n, Fib(n-1, d) + Fib(n-2, d))

但是当我可以调用它时

d={0:1, 1:1}
print(f(2, d))

,甚至使用 f(1,d),它进入无限循环,并重新启动内核。事实上,任何这种形式的函数,比如说

def f(n, d):
    return d.setdefault(n, f(n-1,d))

有同样的问题。当我尝试调试它时,我看到 n 不断减小,通过值 1。我想我不明白这个方法的实现。我假设 setdefault 方法首先检查 key 是否在字典中并返回值,如果没有,则将默认值分配给 key 并返回默认值。我在这里缺少什么?(我使用 Python 3.9.1 和 Spyder 4.2.0)

【问题讨论】:

    标签: dictionary recursion setdefault


    【解决方案1】:

    你仍然需要一个基本情况,否则没有什么可以阻止它计算,fib(-1)fib(-2)fib(-99),...

    def fib(n, d):
      return n if n < 2 else d.setdefault(n, fib(n-1, d) + fib(n-2, d))
    
    print(fib(10, {0:0, 1:1}))
    
    55
    

    setdefault 遇到的问题是 python 是一种应用命令语言。这意味着函数参数在调用函数之前进行评估。对于setdefault,我们将评估fib(n-1,d) + fib(n-2,d)我们尝试在d 中查找n

    更好的接口可能是dict.setdefault(key, lambda: somevalue),如果需要设置默认值,则执行 lambda。我们可以在下面写成lazydefault -

    def lazydefault(d, key, lazyvalue):
      if key not in d:
        d[key] = lazyvalue()
      return d[key]
    
    def fib(n, d):
      return lazydefault(d, n, lambda: fib(n-1, d) + fib(n-2, d))
    
    print(fib(10, {0:0, 1:1}))
    
    55
    

    【讨论】:

    • 谢谢,我明白了!我试图返回dict.setdefault(d, n, f(n-1, d)),而Python 试图首先评估输入以便能够调用该函数。所以,必须坚持你的建议return 1 if n &lt; 2 else d.setdefault(n, fib(n-1, d) + fib(n-2, d))。谢谢!。
    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 2012-12-15
    • 2015-12-13
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    相关资源
    最近更新 更多