Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do different methods of same object have the same `id`? [duplicate]

Tags:

python

I thought that is operator checks the objects id's equality. But it doesn't seem so:

>>> class A(object):
...   def f(): return 1
...   def g(): return 2
...
>>> a = A()
>>> a.f is a.g
False
>>> id(a.f) == id(a.g)
True
like image 713
Timur Avatar asked Feb 03 '16 09:02

Timur


1 Answers

Python reuses the same memory location as you hold no other references to the objects, once id(a.f) is evaluated there are more references to the object so it is gc'd then python is free to reuse the same memory location for a.g. if you assign the methods to names you will see different behaviour:

# creates a reference to the method f
In [190]: f = a.f
# creates a reference to the method g
In [191]: g = a.g
# cannot reuse the memory location of f as it is still referenced
In [192]: id(f) == id(g)
Out[192]: False

You actually really only need store a reference to f to see the same behaviour as above.

In [201]: f = a.f

In [202]: id(f) == id(a.g)
Out[202]: False

You can see the reference count with sys.getrefcount or gc.gc.get_referrers:

In [2]: import gc

In [3]: f = a.f

In [4]: len(gc.get_referrers(a.g)),len(gc.get_referrers(f))
Out[4]: (0, 1)

In [5]: sys.getrefcount(a.g),sys.getrefcount(f)
Out[5]: (1, 2)

The only reason you see 1 for a.g is because The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to getrefcount(). It is analogous to your own example, after the method is evaluated you will still have a reference to to f, with a.g the refcount would be 0 so it is immediately garbage collected and python is free to use the memory location for anything else.

It is also worth noting that the behaviour is not limited to methods but it is just a cpython implementation detail and not something that you should ever rely on:

In [67]: id([]), id([])
Out[67]: (139746946179848, 139746946179848)

In [73]: id(tuple()),id([]),id([])
Out[73]: (139747414818888, 139746946217544, 139746946217544)

In [74]: id([]),id([]),id([])
Out[74]: (139746946182024, 139746946182024, 139746946182024)

In [75]: id([]),id(tuple()),id([])
Out[75]: (139746946186888, 139747414818888, 139746946186888)

In [76]: id(tuple()),id([]),id(tuple())
Out[76]: (139747414818888, 139746946217736, 139747414818888)
like image 74
Padraic Cunningham Avatar answered Oct 22 '22 05:10

Padraic Cunningham