Python是否有更简洁的方法来表达“如果x包含a|b|c|d...”?

77

检查字符串x是否为字符串y的子字符串的Pythonic方式是:

if x in y:

判断x是否等于abcdefg也是Pythonic的:

if x in [a,b,c,d,e,f,g]:

但检查某个字符串x是否包含abcdefg似乎很笨重:

if a in x or b in x or c in x or d in x or e in x or f in x or g in x

有没有更加符合Python风格的方法来检查字符串x是否包含列表中的元素?

我知道使用循环或正则表达式自己编写代码很容易实现:

re.search('(dog|cat|bird|mouse|elephant|pig|cow)', x)

但我在想是否有一种更简洁的方法,不需要使用正则表达式。

4个回答

124

使用any()是Pythonic的做法:

if any(s in x for s in (a,b,c,d,e,f,g)):

来自相关文档:

any(可迭代对象)

如果可迭代对象中的任何一个元素为真,则返回True。如果可迭代对象为空,则返回False。等同于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False
此外,请注意我在这里使用了元组而不是列表。如果您的a-g值是预定义的,则确实更适合使用元组。请参阅:Python中,元组比列表更高效吗?

19
我认为内层括号可以增加可读性。 - arshajii
你也可以使用 if any(s in x for s in "abcdefg"),因为字符串也是可迭代的。 - chepner
6
您无法这样做。a、b、c等是变量,而不是字符! - Markon
是的,我刚刚意识到了 :) - chepner
1
@CeasarBautista 不,那完全不同。你所检查的是x中任何字符是否在集合{a,...,g}中,这不是我们想要的。 - arshajii
显示剩余4条评论

27
if any(q in x for q in [a,b,c,d,e,f,g]):

我认为这就是最简洁和最符合Python编程风格的写法了。


10

有点晚了,但是

not frozenset(x).isdisjoint(frozenset(y))

会起作用,并且算法上可能更快一些(但在较小的测试案例中可能不是这样)。


4
我觉得这个更难读。 - gerrit
这相当晦涩。 - siledh
@siledh 不是很确定,它在其他一些答案中提到过,使用set和类似类型会降低查找成本的事实也不太深奥。 - Snakes and Coffee

3

使用 max 函数而不使用任何其他函数。

def is_in(symbol, lst):
    return max([symbol in x for x in lst]) 

print is_in('a',['ae','br','tl'])
print is_in('c',['ae','br','tl'])

提供

>>> 
True
False

max(...)max([...])更快。 - pts
5
any(...) 比用 max(...) 要快得多... - shx2
是的,any 更可取,因为它会在找到匹配项时短路,而 max 则每次都会检查每个字符串。 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接