id() collisions on bound methods [was: metaclass and customization with parameters]

Jeff Epler jepler at unpythonic.net
Wed Oct 6 02:08:29 CEST 2004


For an instance i with a method m, the expression 'i.m' *creates* (each
time) a bound method object from i.__class__.m.

>>> class C:
...     def f(self): pass
...
>>> c = C()
>>> [c.f for i in range(3)]
[<bound method C.f of <__main__.C instance at 0xf6f7488c>>, <bound
method C.f of <__main__.C instance at 0xf6f7488c>>, <bound method C.f of
<__main__.C instance at 0xf6f7488c>>]
>>> [id(m) for m in _]  # All distinct
[-151250548, -151134580, -151178020]
>>> id(c.f)   # Same as "first one" from earlier.
-151250548

In your example, the bound method 'mc.method0' can be discarded (it is
no longer referencable) before the next statement, so it is possible for
the result of the next expression to have the same id().  The same goes
for the last 'id(c.f)' line, all the bound methods created in the [c.f]
listcomp are unreachable, and objects with the same id can now be
created.

Here's another one for you:
>>> id(200)
138049956
>>> id(300)
138049956
>>> id(400)
138049956

Again, the integer in each expression can be discarded, so it is
possible for an object with the same id to be created in a later
expression.

Python guarantees that two distinct objects alive *at the same time*
have different ids.  Each of these examples has objects with dijoint
lifetimes.

Now, the next thing you may run in to is that immutable objects are
never guaranteed to be distinct.  Sometimes they are, sometimes they
aren't.

Here are some actual examples from Python 2.3.3:
>>> (1,) is (1,)   # Only the empty tuple is special (may differ in 2.4)
False
>>> x = 100        # small integer cache doesn't go this high
>>> y = 100
>>> x is y
False
>>> 50 * 2 is 50 * 2  # Same principle as above
False
>>> x = "rhubarb"  # string literals are interned, but result of + is not
>>> "rhu" + "barb" is x
False

>>> () is ()       # Empty tuple is a special case
True
>>> 100 is 100     # Because 100 is in the bytecode's constants
True
>>> 2 * 2 is 2 * 2 # Because 4 is in the small integer cache
True
>>> x = "rhubarb"  # Because both strings are literals
>>> y = "rhubarb"
>>> x is y
True

For each of these sequences, Python is free to print either 'True' or
'False' (because they deal with the distinctness of immutable objects)
and the actual result depends on implementation choices of CPython
2.3.3.

Jeff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20041005/055d0cda/attachment.pgp>


More information about the Python-list mailing list