当我浏览Python 3的教程时,我遇到了以下内容:
>>> '' in 'spam'
True
我的理解是''
等于没有空格。
当我尝试以下shell终端时,我得到下面显示的输出:
>>> '' in ' spam '
True
有人可以帮忙解释一下发生了什么吗?
答案 0 :(得分:15)
''
是空字符串,与""
相同。空字符串是每个其他字符串的子字符串。
当a
和b
为字符串时,表达式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
对任何字符串x
都返回True:
>>> '' in 'spam'
True
>>> "" in 'spam'
True
>>> "" in ''
True
>>> '' in ""
True
>>> '' in ''
True
>>> '' in ' '
True
>>> "" in " "
True
答案 1 :(得分:4)
string literal ''
表示空字符串。这基本上是一个长度为零的字符串,不包含任何字符。
in
运算符定义为for sequences,如果True
的项目等于s
,则返回“x
,否则False
”表达式x 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
在算法上,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]
''
s
作为空字符串本身甚至是正确的,因为序列切片被定义为在指定序列之外的范围时返回空序列(这就是为什么你可以s[74565463:74565469]
开启短串)。
这就解释了为什么在将空字符串作为子字符串检查时,in
的包含检查始终返回True
。但即使您从逻辑上考虑它,您也可以看到原因:子字符串是字符串的一部分,您可以在另一个字符串中找到它。然而,空字符串可以在之间找到每两个字符。这就像你可以为一个数字添加无限量的零,你可以在字符串中添加无限量的空字符串,而无需实际修改该字符串。
答案 2 :(得分:1)
正如Rushy Panchal指出的,in
包含运算符遵循集合理论约定,并假设空字符串是任何字符串的子字符串。
您可以尝试通过考虑以下因素来说服自己为什么这有意义:让s
成为'' in s == False
的字符串。然后'' in s[len(s):]
最好是传递性错误(或者有s
的子集包含''
,但s
不包含''
等。但后来'' in '' == False
,这也不是很好。因此,您无法选择任何字符串s
,因此'' not in s
不会产生问题。
当然,如果有疑问,请模拟它:
s = input('Enter any string you dare:\n')
print('' in '')
print(s == s + '' == '' + s)
print('' in '' + s)