我正在研究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))
参数A
,k
和n
是要搜索的输入列表,密钥以及子列表所在的原始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"
永远不会被我的条件所返回,那么为什么我放在那里有什么价值呢?
为什么这两个陈述的评价方式不同?
答案 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_value
和continue_recursing()
。当您的功能碰到基本情况时,您的功能不会停止。
答案 1 :(得分:1)
问题是这两个陈述不相同。在工作“if”的情况下,每轮只调用b
一次。在注释掉的“tuple boolean”情况下,在选择与布尔选择器一起使用的条件之前,先评估两个b
条件。由于b
是递归的,并且您始终运行“坏”非终止端以及“良好”终止端,因此会出现最大递归错误。