有没有更好的方法在Python中编写连续的"或"语句?

ere*_*eOn 22 python conditional

我自己找不到任何"好"答案的简单问题:

假设我有以下条件:

if 'foo' in mystring or 'bar' in mystring or 'hello' in mystring:
    # Do something
    pass
Run Code Online (Sandbox Code Playgroud)

or根据情况,声明的数量可以更长.

在不牺牲性能的情况下,是否有一种"更好"(更多Pythonic)的写法方式?

如果考虑使用,any()但它需要一个类似布尔元素的列表,所以我必须首先构建该列表(在此过程中放弃短路评估),所以我猜它效率较低.

非常感谢你.

glg*_*lgl 30

一种方式可能是

if any(s in mystring for s in ('foo', 'bar', 'hello')):
    pass
Run Code Online (Sandbox Code Playgroud)

你迭代的东西是一个元组,它是在编译函数的基础上构建的,所以它不应该低于原始版本.

如果你担心元组会变得太长,你可以做到

def mystringlist():
    yield 'foo'
    yield 'bar'
    yield 'hello'
if any(s in mystring for s in mystringlist()):
    pass
Run Code Online (Sandbox Code Playgroud)

  • 不.`(s在'foo','bar','hello'中的s的mystring中)`是一个生成器表达式,这意味着它不是作为一个整体立即计算的,只是按需的.`any()`在看到第一个真值时停止迭代,所以其余的都不会被检查.阅读生成器表达式. (9认同)
  • 它是一个生成器,而不是一个列表. (2认同)
  • @gnibbler:我没有说'any`没有短路.我担心**清单建设**不会.但由于它实际上是一个发电机,它会改变一切. (2认同)
  • OTOH,如果你做了'任何([s in s in in ...]),你就不会有短路.`[]`列表推导总是创建一个完整的列表; `any()`不会迭代它,但它仍然会在`any`调用之前被评估. (2认同)

cha*_*ite 7

这听起来像是一个正则表达式的工作.

import re

if re.search("(foo|bar|hello)", mystring):
    # Do something
    pass
Run Code Online (Sandbox Code Playgroud)

它也应该更快.特别是如果你提前编译正则表达式.

如果您正在自动生成正则表达式,则可以使用re.escape()以确保没有特殊字符会破坏正则表达式.例如,如果words是您要搜索的字符串列表,则可以生成如下所示的模式:

pattern = "(%s)" % ("|".join(re.escape(word) for word in words), )
Run Code Online (Sandbox Code Playgroud)

您还应该注意,如果您有m单词并且您的字符串包含n字符,则原始代码具有O(n*m)复杂性,而正则表达式具有O(n)复杂性.即使Python正则表达式不是真正的理论comp-sci正则表达式,并且并不总是 O(n)复杂性,在这个简单的情况下它们是.

  • 但是,如果您要查找的任何"单词"包含特殊的正则表达式字符,则必须小心 (4认同)
  • 确实更快!http://ideone.com/MLgCU可能是因为正则表达式只需要遍历字符串一次. (2认同)