缓存版递归斐波那契代码疑问:第3行逻辑运算解析求助
嘿,咱们来把这行看起来有点绕的代码拆解开,核心是搞懂Python逻辑运算符的两个特性:短路求值,以及它们返回的是实际运算值而非单纯的布尔值——这也是这行代码和常规条件判断写法不一样的地方。
首先先把原代码格式化清楚,方便对照:
cache = {} def fiba(n): cache[n] = cache.get(n, 0) or (n <= 1 and 1 or fiba(n-1) + fiba(n-2)) return cache[n] n = 0 x = 0 while fiba(x) <= 4000000: if not fiba(x) % 2: n = n + fiba(x) x=x+1 print(n)
逐部分拆解第三行的逻辑
咱们把cache[n] = cache.get(n, 0) or (n <= 1 and 1 or fiba(n-1) + fiba(n-2))拆成两部分看:
1. 左边的cache.get(n, 0)
这个很简单:从缓存字典cache里获取键n对应的值,如果n不在缓存里,就返回默认值0。
2. 关键的or运算符逻辑
Python里的or是短路求值:如果左边的表达式为“真”(非0、非空、非False等),就直接返回左边的值,根本不会计算右边的表达式;只有左边为“假”时,才会去计算右边的表达式并返回它的值。
所以这里的逻辑是:如果缓存里已经有n的值(也就是cache.get(n,0)不是0),那就直接把这个缓存值赋值给cache[n](相当于复用缓存,避免重复计算);如果缓存里没有,才会执行右边的递归计算逻辑。
3. 右边的(n <= 1 and 1 or fiba(n-1) + fiba(n-2))
这里又嵌套了and和or,同样利用短路求值和返回实际值的特性:
- 先看
n <= 1 and 1:- 如果
n <= 1是真(比如n=0或1),and会返回后面的1(因为左边为真时,and会返回右边的值); - 如果
n > 1是假,and会直接返回False(左边为假时,and不会计算右边,直接返回左边的假值)。
- 如果
- 然后这个结果再和
fiba(n-1) + fiba(n-2)做or运算:- 如果前面得到的是
1(也就是n<=1的情况),or直接返回1; - 如果前面得到的是
False(n>1的情况),or就会计算并返回递归求和的结果fiba(n-1)+fiba(n-2)。
- 如果前面得到的是
等价的清晰写法
其实这行tricky的逻辑完全可以写成可读性更高的条件判断,效果是一样的:
def fiba(n): if n in cache: # 缓存存在,直接复用 return cache[n] if n <= 1: res = 1 else: res = fiba(n-1) + fiba(n-2) cache[n] = res return res
这种写法就直白多了,不容易出错——比如如果斐波那契的初始条件是n=0返回0,那原来的and/or写法就会出问题(因为0是假值,会走到or的递归分支),而条件判断写法就不会有这个隐患。
补充:整个代码的功能
顺便提一句,这段代码的目的是计算所有不超过4000000的偶数斐波那契数的和,用缓存是为了避免递归重复计算,提升效率。
内容的提问来源于stack exchange,提问作者Cosmin Chiriac

