元组布尔评估的意外行为

时间:2015-11-13 18:07:11

标签: python python-2.7

我正在研究code golf并尝试使用元组布尔评估语法((a,b)[bool])编写递归函数。我的功能如下(有一些有用的打印):

def b(A,k,n):
 m=len(A)/2
 print "A: ", A
 print "m: ", m
 print "n: ", n
 print "A[m]", A[m]
 if A[m]==k:return m+n
 # return (m+n,(b(A[m:],k,m+n),b(A[:m],k,n))[A[m]<k])[A[m]!=k]
 return m+n if A[m]==k else (b(A[:m],k,n) if A[m]>k else b(A[m:],k,m+n))

参数Akn是要搜索的输入列表,密钥以及子列表所在的原始A中的索引。 m是列表的中间条目。如果我在[1,2,3,4,5,6,7]搜索6,我希望看到以下输出

A:  [1, 2, 3, 4, 5, 6, 7]
m:  3
n:  0
A[m] 4
A:  [4, 5, 6, 7]
m:  2
n:  3
A[m] 6

使用未注释的return语句生成正确的输出和结果。但是,当我尝试使用注释的return语句(应该是等效的)时,我收到一个递归深度错误。

此外,如果我用一个确定值替换其中一个递归调用,然后在边缘上搜索一个值,它将按预期运行。例如,如果6语句为:

,则[1,2,3,4,5,6,7]中的return搜索工作正常
return (m+n,(b(A[m:],k,m+n),"anyValue")[A[m]>k])[A[m]!=k]
在这种情况下,

"anyValue"永远不会被我的条件所返回,那么为什么我放在那里有什么价值呢?

为什么这两个陈述的评价方式不同?

2 个答案:

答案 0 :(得分:2)

当你这样做时

thing() if condition else other_thing()

仅评估thing()other_thing()中的一个。没有返回的那个根本没有被评估,所以你可以做像

这样的事情
base_case_value if base_case_condition else continue_recursing()

并且递归将在基本情况下停止。

当你这样做时

(continue_recursing(), base_case_value)[base_case_condition]

Python需要在索引之前构建元组,因此无论如何都会评估base_case_valuecontinue_recursing()。当您的功能碰到基本情况时,您的功能不会停止。

答案 1 :(得分:1)

问题是这两个陈述不相同。在工作“if”的情况下,每轮只调用b一次。在注释掉的“tuple boolean”情况下,在选择与布尔选择器一起使用的条件之前,先评估两个b条件。由于b是递归的,并且您始终运行“坏”非终止端以及“良好”终止端,因此会出现最大递归错误。