用连字符比较两个Python字符串

5
我将尝试在Python中比较两个字符串,并注意到当字符串中存在连字符/破折号时,它们不会相等。例如:
>>>teststring = 'newstring'
>>>teststring is 'newstring'
True

然后,如果我添加一个破折号
>>>teststring = 'new-string'
>>>teststring is 'new-string'
False

为什么会这样,以及用什么方法最好比较带破折号的字符串?

测试相等性,而不是身份。使用== - Martijn Pieters
2个回答

4

在比较相等性时,你永远不应该使用isis用于测试身份(identity),应该使用==

说实话,我不知道为什么'newstring' is 'newstring'。我确信这因Python实现而异,因为它似乎是一个节省内存的缓存,以重复使用短字符串。

然而:

teststring = 'newstring'
teststring == 'newstring' # True

nextstring = 'new-string'
nextstring == 'new-string' # True

基本上,is 的作用是测试 id 是否完全相同。
id('new-string') # 48441808
id('new-string') # 48435352
# These change
id('newstring') # 48441728
id('newstring') # 48441728
# These don't, and I don't know why.

2
请参考 关于Python不可变字符串ID的更改,了解为什么is有时候会起作用。 - Martijn Pieters
3
在我的回答中,*[T]he Python compiler will also intern any Python string stored as a constant, provided it is a valid identifier. The Python code object factory function PyCode_New will intern any string object that contains only letters, digits or an underscore* 的意思是:如果Python字符串是一个合法的标识符并被存储为常量,Python编译器也会将其设为内部对象。同时,Python的代码对象工厂函数PyCode_New将对任何只包含字母、数字或下划线的字符串对象进行内部化处理。 - Martijn Pieters
这里更深入地介绍了默认情况下会被内部化的内容:http://guilload.com/python-string-interning/ - Ray

0

在字符串比较中,您不应使用is。is检查两个对象是否相同。您应该在这里使用等号运算符==。它比较对象的值,而不是对象的ID。

在这种情况下,看起来Python正在对字符串对象进行一些对象优化,因此出现了这种行为。

>>> teststring = 'newstring'
>>> id(teststring)
4329009776
>>> id('newstring')
4329009776
>>> teststring = 'new-string'
>>> id(teststring)
4329009840
>>> id('new-string')
4329009776
>>> teststring == 'new-string'
True
>>> teststring is 'new-string'
False

1
关于Python不可变字符串的ID更改,请参见关于Python字符串内部化(以及标识测试的工作方式)的更改ID - Martijn Pieters
有道理。所以这与Python对0-255整数对象的处理方式类似,这些对象始终存在于内存中。Python从不为这些整数创建新对象,只在需要时添加引用计数。 - ronakg
1
确实。但这只是一个实现细节,而不是您的代码应该依赖的内容。 - Martijn Pieters

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