"是"操作员没有按预期工作

时间:2015-03-10 12:32:36

标签: python

看看这段代码:

import re

ti = "abcd"
tq = "abcdef"
check_abcd = re.compile('^abcd')
print id(check_abcd.search(ti))
print id(check_abcd.search(tq))
print check_abcd.search(ti)
print check_abcd.search(tq)
if check_abcd.search(ti) is check_abcd.search(tq):
    print "Matching"
else:
    print "not matching"

输出:

41696976
41696976
<_sre.SRE_Match object at 0x00000000027C3ED0>
<_sre.SRE_Match object at 0x00000000027C3ED0>
not matching

is的定义:

`is` is identity testing, == is equality testing. 
 is will return True if two variables point to the same object

1)当id和对象引用相同时,为什么is不返回True

2)当is==替换时,它仍然会返回false。这是使用==比较对象时的预期行为。

3 个答案:

答案 0 :(得分:6)

您从未分配返回值,因此在打印id()调用的返回值的check_abcd.search()值后,Python 会丢弃返回值对象,因为没有任何引用它了CPython对象的生命周期直接由对它们的引用数量决定;一旦引用计数降为0,对象就会从内存中删除。

可以重复使用丢弃的内存位置,因此您希望在id()来电中看到相同的值。请参阅id() documentation

  

返回对象的“标识”。这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。 两个生命周期不重叠的对象可能具有相同的id()值。

在您的代码中,您实际上没有一个对象,您有两个具有非重叠生命周期的独立对象。

如果要确保不重用id()值,请指定返回值:

>>> import re
>>> ti = "abcd"
>>> tq = "abcdef"
>>> check_abcd = re.compile('^abcd')
>>> ti_search = check_abcd.search(ti)
>>> tq_search = check_abcd.search(tq)
>>> id(ti_search), id(tq_search)
(4378421952, 4378422056)
>>> ti_search, tq_search
(<_sre.SRE_Match object at 0x104f96ac0>, <_sre.SRE_Match object at 0x104f96b28>)
>>> ti_search is tq_search
False

通过分配check_abcd.search()(正则表达式MatchObject s)的返回值,将创建一个额外的引用,并且Python无法重用内存位置。

答案 1 :(得分:2)

你做什么: print id(check_abcd.search(ti))在一行中,并且不会将search的返回值存储在任何位置,其引用计数将归零并且会被销毁。线路中的调用创建了另一个对象,该对象恰好位于相同的内存地址中(CPython将其用作对象ID) - 但它不是同一个对象。

当您使用is运算符时,仍然必须存在上一个对象才能进行比较,并且其地址将不同。

在打印ID(并使用不同的变量)之前,只需将调用结果放入变量check_abcd.search,您就能看到实际发生的情况。

此外:如果你想了解&#34;是&#34;的行为,继续这些方面可能是有益的。和对象ID - 但是如果你想比较字符串和返回值,只需使用==运算符,从不is:后续函数调用,即使返回相同的值也不应该返回相同的值object - 仅在与&#34; None&#34;进行比较时才建议进行is比较。 (实现为单身)

答案 2 :(得分:2)

Martjin已经给出了正确的答案,但是为了进一步澄清,这里有一个带注释的版本代码中发生了什么:

# this line creates returns a value from .search(), 
# prints the id, then DISCARDS the value as you have not 
# created a reference using a variable.
print id(check_abcd.search(ti)) 

# this line creates a new, distinct returned value from .search()
# COINCIDENTALLY reusing the memory address and id of the last one.
print id(check_abcd.search(tq))

# Same, a NEW value having (by coincidence) the same id
print check_abcd.search(ti)

# Same again
print check_abcd.search(tq)

# Here, Python is creating two distinct return values.  
# The first object cannot be released and the id reused
# because both values must be held until the conditional statement has 
# been completely evaluated.  Therefore, while the FIRST value will
# probably reuse the same id, the second one will have a different id.
if check_abcd.search(ti) is check_abcd.search(tq):
    print "Matching"
else:
    print "not matching"