Python 3.0中带有空字符串的"IN"运算符

Bri*_*hts 10 python string python-3.x

当我浏览Python 3的教程时,我遇到了以下内容:

>>> '' in 'spam'
True
Run Code Online (Sandbox Code Playgroud)

我的理解是''等于没有空格.

当我尝试以下shell终端时,我得到下面显示的输出:

>>> '' in ' spam '
True
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙解释一下发生了什么吗?

Rus*_*hal 15

''是空字符串,与...相同"".空字符串是每个其他字符串的子字符串.

ab是字符串时,表达式a in b检查a是否为子字符串b.也就是说,a必须存在的字符序列b; 必须有一个i这样的指数b[i:i+len(a)] == a.如果a为空,则任何索引都i满足此条件.

这并不意味着当你迭代时b,你会得到a.与其他序列不同,虽然for a in b满足所产生的每个元素a in b,a in b并不意味着a将通过迭代产生b.

所以'' in x"" in x为任何字符串返回True x:

>>> '' in 'spam'
True
>>> "" in 'spam'
True
>>> "" in ''
True
>>> '' in ""
True
>>> '' in ''
True
>>> '' in ' ' 
True
>>> "" in " "
True
Run Code Online (Sandbox Code Playgroud)

  • @Brightlights字符串的迭代器遍历每个1个字符的子字符串(即每个字符).空字符串不是字符串的字符.但是,`in`运算符,包含检查,只检查字符串'a`是否包含在`b`中的子字符串中.你可以在字符串的每个零长度子字符串中找到空字符串,因此对于每个字符串`x`,x'中的'''为真. (2认同)
  • @Brightlights:`for'in'spam':print(i)`也不会打印''am'`,即使'am'是''spam'的子串.这是因为`for in in'spam'`不会迭代所有子字符串,它会迭代所有字符.如果你以某种方式迭代所有子串,它确实包括`''`. (2认同)

pok*_*oke 5

字符串字面 ''表示空字符串。这基本上是一个长度为零的字符串,其中不包含任何字符。

in运算符是为序列定义的以便为表达式返回“True如果 的项s等于x,否则Falsex in s。对于一般序列,这意味着s(通常使用迭代可访问)中的项目之一等于测试元素x。然而,对于字符串,in运算符具有子序列语义。所以x in s是真实的,当x是的子串s

形式上,这意味着对于x长度为 的子字符串n,必须有一个i满足以下表达式的索引:s[i:i+n] == x

这通过一个例子很容易理解:

>>> s = 'foobar'

>>> x = 'foo'
>>> n = len(x) # 3
>>> i = 0
>>> s[i:i+n] == x
True

>>> x = 'obar'
>>> n = len(x) # 4
>>> i = 2
>>> s[i:i+n] == x
True
Run Code Online (Sandbox Code Playgroud)

从算法上讲,in操作符(或底层__contains__方法)需要做的是迭代i所有可能的值 ( 0 <= i < len(s) - n) 并检查条件是否为真i

回顾空字符串,很清楚为什么'' in s每个字符串的检查都是真的s:n为零,所以我们正在检查s[i:i]; 这是每个有效索引的空字符串本身i

>>> s[0:0]
''
>>> s[1:1]
''
>>> s[2:2]
''
Run Code Online (Sandbox Code Playgroud)

甚至s作为空字符串本身也是如此,因为序列切片被定义为在指定序列之外的范围时返回一个空序列(这就是您可以s[74565463:74565469]对短字符串执行的原因)。

所以这就解释了为什么当检查空字符串作为子字符串时,包含检查in总是返回True。但即使您从逻辑上考虑它,您也可以看到原因:子字符串是您可以在另一个字符串中找到的字符串的一部分。但是可以每两个字符之间找到空字符串。就像您可以向数字添加无限数量的零一样,您可以向字符串添加无限数量的空字符串而无需实际修改该字符串。