Reputation: 27946
Please consider the following
class A(object):
def foo(self):
pass
a = A()
# accessing a's foo seems consistent
init1 = a.foo
init2 = a.foo
assert init1 == init2
assert id(a.foo) == id(a.foo)
# Or is it?
foos= [a.foo for i in range(10)]
ids = [id(foo) for foo in foos]
for i, id_ in enumerate(ids):
for j, id__ in enumerate(ids):
if i != j:
assert id_ != id__
It appears id(a.foo)
can equal to id(a.foo)
and can not equal to id(a.foo)
, but I can't understand when it is the same and when it isn't.
Please explain what's going on here.
Upvotes: 3
Views: 234
Reputation: 6908
The transformation of a function to an instance method happens every time the instance method attribute is accessed, so the id should be different every time, at least in the sense that a new object has been created. (see Python Data Model for details about method transformation and descriptors)
The problem is doing this:
assert id(a.foo) == id(a.foo)
There are times the Python garbage collector can work so fast that even within a single expression, two different objects can have the same id, because the object has already been reclaimed once id()
is done with it.
If you do this:
assert id(init1) == id(init2)
you'll see that they in fact have different ids.
Update: to address the question about why init1 == init2
is True
: init1
and init2
are method wrapper objects that refer to the same function in the same class, so the method wrapper's __eq__()
considers them equal.
Upvotes: 6
Reputation: 219
Note that the 2 id
of the same id
is not the same value:
for example:
a = 1
b =1
print(id(a))
print(id(b))
print(id(a))
will give me this result:
9788992
9788992
9788992
but
print(id(id(a)))
print(id(id(a)))
will give this:
140331099421680
140331099421648
foos= [a.foo for i in range(10)]
gives the same id
valou to each one.
But the id
of the id's in foos
is not the same value.
Therefore:
ids = [id(foo) for foo in foos]
Gives different values to each one.
Upvotes: -1
Reputation: 131
assert id(a.foo) is a type, not a number or variable.
each instance has a unique ID so ID of a.foo does not equal ID of a.foo's second instance. You are looking for a boolean variable.(True/False)
So basically you are comparing something like the following:
# First instance (object in memory)
a.foo == building 1 apt 1
#second instance (object in memory)
a.foo ==building 1 apt 1
a.foo == a.foo # boolean value "True"
# First instance of ID a.foo
id(a.foo) == building 1 apt 1
# Second instance of ID a.foo
id(a.foo) == building 2 apt 1
id(a.foo) == id(a.foo) Boolean value "False".
While the above example is not technically correct. It gives you a better understanding of what is going on. What actually is happening is instance a.foo #1 gives a memory location and a.foo # 2 gives another memory location and even though the two values are the same the location in memory is not.
I hope this helps clarify things a bit for you.
Try this. add the following code to the end of your script:
print(a)
print(id(a))
Now run it 2 times. The ID's change. and the memory location does too.
Upvotes: -1