有时我发现算法逻辑的简洁表达比冗长的表达更直观。一个例子是二分搜索(维基百科),一个简单的 Python 实现如下:
def binary_search(A, L, R, T):
while L != R:
M = (L + R + 1) // 2
if A[M] > T:
R = M - 1
else:
L = M
if A[L] == T:
return L
else:
return -1
(注意:我已经引入L
和R
参数作为要搜索的排序数组参数中间隔的第一个和最后一个索引A
,而不是使用维基百科页面的伪代码中n
的长度参数。)A
依赖条件表达式和赋值表达式(海象运算符)的更短的实现是:
def binary_search(A, L, R, T):
while L != R:
L, R = (L, M - 1) if A[M := (L + R + 1) // 2] > T else (M, R)
return L if A[L] == T else -1
对我来说,虽然单行循环体很简洁,严格来说可能比使用传统 if/else 块的展开循环体需要更多的操作,但最好是它不需要眼睛上下移动通过代码来掌握发生了什么。它告诉我,在第一次更新M
为当前搜索区间的中点之后L, R
,我们然后通过缩小它来更新该区间,使其左侧相同,右侧减少,反之亦然,具体取决于 的相对值排序后的输入数组中的中点值A
和目标值T
。
事实上,如果我说实话,我真正想做的是:
def binary_search(A, L, R, T):
while L != R:
(L, R := M - 1) if A[M := (L + R + 1) // 2] > T else (L := M, R)
return L if A[L] == T else -1
我想知道上面的第二个和第三个代码示例是否有任何样式指南通知禁令,或者这些是否被认为是海象运算符的风格上可接受的用途?