Python是否有字符串“包含”子字符串方法?

我正在寻找Python中的string.containsstring.indexof方法。

我想做:

if not somestring.contains("blah"):continue
6237437 次浏览

如果只是子字符串搜索,您可以使用string.find("substring")

不过,您必须对#0#1#2小心一点,因为它们是子字符串搜索。换句话说,这:

s = "This be a string"if s.find("is") == -1:print("No 'is' here!")else:print("Found 'is' in the string.")

它将打印Found 'is' in the string.类似地,if "is" in s:将评估到True。这可能是也可能不是您想要的。

使用#0运算符

if "blah" not in somestring:continue

if needle in haystack:是正常用法,正如@Michael所说,它依赖于#1运算符,比方法调用更具可读性和更快。

如果你真的需要一个方法而不是运算符(例如,为了一个非常奇特的排序做一些奇怪的key=…?),那就是#1。但是由于你的例子是在if中使用的,我猜你并不是真正的意思;-)。直接使用特殊方法不是好的形式(也不可读,也不高效)--它们应该通过委托给它们的运算符和内置函数来使用。

Python有字符串包含子字符串的方法吗?

99%的用例将使用关键字in来覆盖,它返回TrueFalse

'substring' in any_string

对于获取索引的用例,使用str.find(失败时返回-1,并且具有可选的位置参数):

start = 0stop = len(any_string)any_string.find('substring', start, stop)

str.index(类似于find,但在失败时引发ValueError):

start = 100end = 1000any_string.index('substring', start, end)

补充说明

使用in比较运算符,因为

  1. 该语言旨在使用它,并且
  2. 其他Python程序员希望您使用它。
>>> 'foo' in '**foo**'True

相反的(补语),原始问题所要求的,是not in

>>> 'foo' not in '**foo**' # returns FalseFalse

这在语义上与not 'foo' in '**foo**'相同,但它更具可读性,并且在语言中明确提供作为易读性改进。

避免使用__contains__

“包含”方法实现了in的行为。这个例子,

str.__contains__('**foo**', 'foo')

返回True。您也可以从超字符串的实例调用此函数:

'**foo**'.__contains__('foo')

但是不要。以下划线开头的方法在语义上被认为是非公共的。使用它的唯一原因是在实现或扩展innot in功能时(例如,如果子类化str):

class NoisyString(str):def __contains__(self, other):print(f'testing if "{other}" in "{self}"')return super(NoisyString, self).__contains__(other)
ns = NoisyString('a string with a substring inside')

现在:

>>> 'substring' in nstesting if "substring" in "a string with a substring inside"True

不要使用findindex来测试“包含”

不要使用以下字符串方法来测试“包含”:

>>> '**foo**'.index('foo')2>>> '**foo**'.find('foo')2
>>> '**oo**'.find('foo')-1>>> '**oo**'.index('foo')
Traceback (most recent call last):File "<pyshell#40>", line 1, in <module>'**oo**'.index('foo')ValueError: substring not found

其他语言可能没有直接测试子字符串的方法,因此您必须使用这些类型的方法,但对于Python,使用in比较运算符要有效得多。

此外,这些不是in的直接替换。您可能必须处理异常或-1情况,如果它们返回0(因为它们在开头找到了子字符串),布尔解释是False而不是True

如果你的意思是not any_string.startswith(substring),那就说出来。

性能比较

我们可以比较实现同一目标的各种方法。

import timeit
def in_(s, other):return other in s
def contains(s, other):return s.__contains__(other)
def find(s, other):return s.find(other) != -1
def index(s, other):try:s.index(other)except ValueError:return Falseelse:return True


perf_dict = {'in:True': min(timeit.repeat(lambda: in_('superstring', 'str'))),'in:False': min(timeit.repeat(lambda: in_('superstring', 'not'))),'__contains__:True': min(timeit.repeat(lambda: contains('superstring', 'str'))),'__contains__:False': min(timeit.repeat(lambda: contains('superstring', 'not'))),'find:True': min(timeit.repeat(lambda: find('superstring', 'str'))),'find:False': min(timeit.repeat(lambda: find('superstring', 'not'))),'index:True': min(timeit.repeat(lambda: index('superstring', 'str'))),'index:False': min(timeit.repeat(lambda: index('superstring', 'not'))),}

现在我们看到使用in比其他方法快得多。做等效操作的时间越少越好:

>>> perf_dict{'in:True': 0.16450627865128808,'in:False': 0.1609668098178645,'__contains__:True': 0.24355481654697542,'__contains__:False': 0.24382793854783813,'find:True': 0.3067379407923454,'find:False': 0.29860888058124146,'index:True': 0.29647137792585454,'index:False': 0.5502287584545229}

如果in使用__contains__in怎么会比__contains__快?

这是一个很好的后续问题。

让我们用感兴趣的方法反汇编函数:

>>> from dis import dis>>> dis(lambda: 'a' in 'b')1           0 LOAD_CONST               1 ('a')2 LOAD_CONST               2 ('b')4 COMPARE_OP               6 (in)6 RETURN_VALUE>>> dis(lambda: 'b'.__contains__('a'))1           0 LOAD_CONST               1 ('b')2 LOAD_METHOD              0 (__contains__)4 LOAD_CONST               2 ('a')6 CALL_METHOD              18 RETURN_VALUE

因此,我们看到.__contains__方法必须单独查找,然后从Python虚拟机调用-这应该充分解释了差异。

以下是您的答案:

if "insert_char_or_string_here" in "insert_string_to_search_here":#DOSTUFF

检查是否为false:

if not "insert_char_or_string_here" in "insert_string_to_search_here":#DOSTUFF

或:

if "insert_char_or_string_here" not in "insert_string_to_search_here":#DOSTUFF

所以显然没有类似的向量比较。一个明显的Python方法是:

names = ['bob', 'john', 'mike']any(st in 'bob and john' for st in names)>> True
any(st in 'mary and jane' for st in names)>> False

in Python字符串和列表

以下是一些关于in方法的有用示例:

>>> "foo" in "foobar"True>>> "foo" in "Foobar"False>>> "foo" in "Foobar".lower()True>>> "foo".capitalize() in "Foobar"True>>> "foo" in ["bar", "foo", "foobar"]True>>> "foo" in ["fo", "o", "foobar"]False>>> ["foo" in a for a in ["fo", "o", "foobar"]][False, False, True]

注意。列表是可迭代的,in方法作用于可迭代的对象,而不仅仅是字符串。

如果您想以更模糊的方式比较字符串以衡量它们的“相似性”,请考虑使用Levenshtein包

下面的答案显示了它是如何工作的。

如果你对"blah" in somestring很满意,但希望它是一个函数/方法调用,你可以这样做

import operator
if not operator.contains(somestring, "blah"):continue

Python中的所有运算符或多或少都可以在操作员模块中找到,包括in

您可以使用正则表达式来获取出现次数:

>>> import re>>> print(re.findall(r'( |t)', to_search_in)) # searches for t or space['t', ' ', 't', ' ', ' ']

您可以使用y.count()

它将返回子字符串在字符串中出现次数的整数值。

例如:

string.count("bah") >> 0string.count("Hello") >> 1