Equality and identity

David M. Cooke cookedm+news at physics.mcmaster.ca
Tue Mar 30 15:03:28 EST 2004


At some point, Marius Bernklev <mariube+netnews+ at ifi.uio.no> wrote:

> In python, it seems like immutable objects are equal under both
> equality and identity:
>
>>>> 5 == 5
> True
>>>> 5 is 5
> True
>>>> "hei" == "hei"
> True
>>>> "hei" is "hei"
> True
>
> But that isn't true for tuples:
>>>> (5,2) == (5,2)
> True
>>>> (5,2) is (5,2)
> False
>
> Why not?  Are tuples mutable in some way I've missed, or are there
> other reasons for this behaviour?  To me, it seems natural to concider
> (5,2) and (5,2) the same object, just like "5,2" and "5,2".

We've had this question recently. Immutable objects *may* be reused,
but are not required. It's implementation-dependent.

Rememeber:
'is' checks object identity
'==' checks object equality

identity implies equality, but not the other way around.

In your example, 5 and "hei", for various reasons, are compiled to
reference the exact same object, so 'is' returns True. However, no
such caching is done with tuples, so (5,2) and (5,2) compile to
references to different objects (whose contents are equal).

Here are some examples that may help some more:
>>> a = "hei x"
>>> b = "hei x"
>>> a is b
False
# The space in "hei x" prevents the string from being interned, so two
# string objects are created)
>>> a = 12345
>>> b = 12345
>>> a is b
False
# integers outside of (about) [-100,100] are not cached, so a and b
# reference different objects)
>>> 12345 is 12345
True
# huh? let's look closer...
>>> import dis
>>> c = compile('12345 is 12345', '<string>', 'single)
# this creates the code object that is executed to evaluate '12345 is 12345'
>>> exec c
True
>>> dis.dis(c)
  1           0 LOAD_CONST               0 (12345)
              3 LOAD_CONST               0 (12345)
              6 COMPARE_OP               8 (is)
              9 PRINT_EXPR          
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE        
# ahh, the compiler optimizes storing constants in the code object.
>>> c = compile('(5,2) is (5,2)', '<string>', 'single')
>>> dis.dis(c)
  1           0 LOAD_CONST               0 (5)
              3 LOAD_CONST               1 (2)
              6 BUILD_TUPLE              2
              9 LOAD_CONST               0 (5)
             12 LOAD_CONST               1 (2)
             15 BUILD_TUPLE              2
             18 COMPARE_OP               8 (is)
             21 PRINT_EXPR          
             22 LOAD_CONST               2 (None)
             25 RETURN_VALUE        
# here we see the compiler optimizes storage for the numbers also, but
# since it builds tuples, instead of storing them in the code object,
# it doesn't store (5,2) as a one object, but constructs two different
# ones that it compares.


Also, here's a example with Jython 2.1:
Jython 2.1 on java1.3 (JIT: kaffe.jit)
Type "copyright", "credits" or "license" for more information.
>>> 12345 is 12345
1
>>> "hei" is "hei"
1
>>> a = "hei"
>>> b = "hei"
>>> a is b
0

Note that the last part gives True when done with CPython, as "hei"
looks like it could be an identifier, and is 'interned' (cached),
whereas Jython doesn't do that.

-- 
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca



More information about the Python-list mailing list