Python:解释器是否像任何语句一样优化语句([inclict for loop])



我想知道python解释器会自动完成哪种类型的优化。例如,我有以下代码来检查字符串是否以startList:中的任何子字符串开头

def startswithAny(string, startList):
return any([string.startswith(x) for x in startList])

假设startList包含1000个条目,但string.startswith(startList[0])已经生成true。会发生什么?[string.startswith(x) for x in startList]还会被全面评估吗?或者解释器会识别出any((已经为true了吗?

如果没有,那么比IMHO更有意义的是编写这样的非Python代码,比如:

def startswithAny(string, startList):
for x in startList:
if string.startswith(x): 
return True
return False

感谢

好吧,any将接受短路。问题是,当您使用列表时,您首先计算完整列表,然后才对完整列表调用any

如果你真的想使用短路,你应该使用生成器而不是列表:

def startswithAny(string, startList):
return any((string.startswith(x) for x in startList))

(方括号替换为括号(

使用timeit演示:

>>> timeit.timeit('any([i.startswith("ab") for i in lst])',
'lst = [ "abc" + str(i) for i in range(10000)]', number=10000)
17.005268767956352
>>> timeit.timeit('any((i.startswith("ab") for i in lst))',
'lst = [ "abc" + str(i) for i in range(10000)]', number=10000)
0.006302962841857607

是的,any函数被保证短路,这意味着当它找到一个为True的元素时,它就终止了。any()代码本质上等效于以下代码:

def any(iterable):
for element in iterable:
if element:
return True
return False

正如您所看到的,当一个元素为True时,循环就会停止。

所以,是的,你最后写的代码本质上相当于在上面运行any()any()是一种更Python的方式。

根据文件,any保证短路。

但是你的使用会破坏这种优化,因为列表理解表达式会对每个元素进行求值,所以你应该传递一个生成器表达式,这意味着更优化的方法是any(string.startswith(x) for x in startList)

最新更新