id functions of ints, floats and strings

Daniel Fetchinson fetchinson at googlemail.com
Fri Apr 4 00:46:46 CEST 2008


> Hi all,
>
> I've been playing around with the identity function id() for different
> types of objects, and I think I understand its behaviour when it comes
> to objects like lists and tuples in which case an assignment r2 = r1
> (r1 refers to an existing object) creates an alias r2 that refers to
> the same object as r1. In this case id(r1) == id(r2)  (or, if you
> like: r1 is r2). However for r1, r2 assigned as follows: r1 = [1, 2,
> 3] and r2 = [1, 2, 3], (r1 is r2) is False, even if r1==r2,
> etc. ...this is all very well. Therefore, it seems that id(r) can be
> interpreted as the address of the object that 'r' refers to.
>
> My observations of its behaviour when comparing ints, floats and
> strings have raised some questions in my mind, though. Consider the
> following examples:
>
> #########################################################################
>
> # (1) turns out to be true
> a = 10
> b = 10
> print a is b
>
> # (2) turns out to be false
> f = 10.0
> g = 10.0
> print f is g
>
> # behaviour when a list or tuple contains the same elements ("same"
> meaning same type and value):
>
> # define the following function, that checks if all the elements in an
> iterable object are equal:
>
> def areAllElementsEqual(iterable):
> 	return reduce(lambda x, y: x == y and x, iterable) != False
>
> # (3) checking if ids of all list elements are the same for different
> cases:
>
> a = 3*[1]; areAllElementsEqual([id(i) for i in a]) # True
> b = [1, 1, 1]; areAllElementsEqual([id(i) for i in b]) # True
> f = 3*[1.0]; areAllElementsEqual([id(i) for i in f]) # True
> g = [1.0, 1.0, 1.0]; areAllElementsEqual([id(i) for i in g]) # True
> g1 = [1.0, 1.0, 0.5+0.5]; areAllElementsEqual([id(i) for i in g1]) #
> False
>
> # (4) two equal floats defined inside a function body behave
> differently than case (1):
>
> def func():
> 	f = 10.0
> 	g = 10.0
> 	return f is g
>
> print func() # True
>
> ######################################################
>
> I didn't mention any examples with strings; they behaved like ints
> with respect to their id properties for all the cases I tried.
> While I have no particular qualms about the behaviour, I have the
> following questions:

Small integers and short strings are cached and reused and for these (
r1 == r2 ) implies ( r1 is r2 ). For longer strings or larger integers
this does not happen and so in general ( r1 == r2 ) does not imply (
r1 is r2 ). The caching and reuse is for performance gains and is an
implementation detail which should not be relied upon.

> 1) Which of the above behaviours are reliable? For example, does a1 =
> a2 for ints and strings always imply that a1 is a2?

No, see above.

> 2) From the programmer's perspective, are ids of ints, floats and
> string of any practical significance at all (since these types are
> immutable)?

You can check identity (and not equality) with them. So whenever you
need that they are practically useful if all you need is equality they
are useless.

> 3) Does the behaviour of ids for lists and tuples of the same element
> (of type int, string and sometimes even float), imply that the tuple a
> = (1,) takes (nearly) the same storage space as a = 10000*(1,)? (What
> about a list, where elements can be changed at will?)

I'm not sure about tuples but for lists the storage space needed for
10000*(1,) is roughly 10000 times more than for (1,).

> Would appreciate your responses...

HTH,
Daniel



More information about the Python-list mailing list