Can(s是“”)和(s ==“”)在Python 2.6.2中会给出不同的结果吗?

时间:2010-07-02 11:39:07

标签: python string identity equality

正如任何Python程序员所知,您应该使用==而不是is来比较两个字符串的相等性。但是,实际上是否存在( s is "" )( s == "" )在Python 2.6.2中会产生不同结果的任何情况?

我最近遇到过在代码审查中使用( s is "" )的代码,虽然指出这是不正确的,但我想举例说明这可能会失败。但是尽可能地尝试,我不能构造两个具有不同身份的空字符串。似乎Python实现必须在许多常见操作中特殊情况下使用空字符串。例如:

>>> a = ""
>>> b = "abc"[ 2:2 ]
>>> c = ''.join( [] )
>>> d = re.match( '()', 'abc' ).group( 1 )
>>> e = a + b + c + d 
>>> a is b is c is d is e
True

但是,this question表明 ( s is "" )( s == "" )可能不同的情况。谁能举个例子呢?

7 个答案:

答案 0 :(得分:12)

Python is测试对象标识而不是相等。以下是使用is==给出不同结果的示例:

>>> s=u""
>>> print s is ""
False
>>> print s==""
True

答案 1 :(得分:11)

正如其他人所说,不要依赖未定义的行为。但是,由于您要求Python 2.6的特定反例,这里是:

>>> s = u"\xff".encode('ascii', 'ignore')
>>> s
''
>>> id(s)
10667744
>>> id("")
10666064
>>> s == ""
True
>>> s is ""
False
>>> type(s) is type("")
True

Python 2.6唯一能够以空字符串形式结束的时间是不正常的空字符串,这是因为它执行字符串操作并且事先不确定该字符串的长度。因此,当您对字符串进行编码时,错误处理程序最终可以剥离字符并在完成后修复缓冲区大小。当然这是一个疏忽,可以在Python 2.7中轻松改变。

答案 2 :(得分:7)

你不应该在乎。与被定义为单例的None不同,没有规则表明只有一个空字符串对象。所以s is ""的结果是依赖于实现的,使用is是NO-NO,无论你是否能找到一个例子。

答案 3 :(得分:3)

它似乎适用于任何实际上字符串,但看起来像字符串的东西(例如str的unicode或子类或类似的东西)将失败。

>>> class mysub(str):
    def __init__(self, *args, **kwargs):
        super(mysub, self).__init__(*args, **kwargs)

>>> 
>>> q = mysub("")
>>> q is ""
False
>>> q == ""
True

修改

用于代码审查和&反馈我建议这是不好的做法,因为它实现了一个意外的测试(即使我们忽略了当类型匹配时它是否总是表现相同的不确定性。)

if x is ""

意味着x具有正确的值并且键入,但是没有明确的类型测试会警告未来的维护者或api用户等。

if x == ""

意味着x只是正确的值

答案 4 :(得分:1)

你找不到一个例子,因为有些东西是独特的而且不是可静态的 - 所以Python只保留了一次,因此is可以工作。这些包括(), '',u'', True, False, None CPython甚至保留了一些常用的数字,即0, 0.0, 1, 1.0,

答案 5 :(得分:0)

可能不会,CPython似乎在所有情况下优化""的虚假实例。但正如其他人所说,不要依赖于此。

答案 6 :(得分:0)

未定义的行为是一个模糊的问题。 Python规范定义的内容和实现必须符合的内容,还有一些事情可供选择。通过查看Python的源代码,您可能会确信这种行为永远不会发生在实际的字符串对象上(与unicode与非unicode和其他接近但不相关的示例不同)。很高兴,你将在代码中留下这样的测试。

但Python实现并不能保证它始终有效。未来的一些实施可能会导致它发生变化,并且您会遇到痛苦的不兼容性。

因此,经验法则很简单:不要这样做。仅将操作符用于其预期和记录良好的用途。不要依赖可能在未来很好地改变的实现工件。