The id()
inbuilt function gives...
an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime.
The is
operator, instead, gives...
object identity
So why is it possible to have two objects that have the same id
but return False
to an is
check? Here is an example:
>>> class Test(): ... def test(): ... pass >>> a = Test() >>> b = Test() >>> id(a.test) == id(b.test) True >>> a.test is b.test False
A more troubling example: (continuing the above)
>>> b = a >>> b is a True >>> b.test is a.test False >>> a.test is a.test False
However:
>>> new_improved_test_method = lambda: None >>> a.test = new_improved_test_method >>> a.test is a.test True
The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory.
== is for value equality. It's used to know if two objects have the same value. is is for reference equality. It's used to know if two references refer (or point) to the same object, i.e if they're identical.
Python id() Function The id() function returns a unique id for the specified object. All objects in Python has its own unique id. The id is assigned to the object when it is created.
id() function returns the identity of the object. type() function returns the type of the object.
>>> b.test is a.test False >>> a.test is a.test False
Methods are created on-the-fly each time you look them up. The function object (which is always the same object) implements the descriptor protocol and its __get__
creates the bound method object. No two bound methods would normally be the same object.
>>> id(a.test) == id(b.test) True >>> a.test is b.test False
This example is deceptive. The result of the first is only True
by coincidence. a.test
creates a bound method and it's garbage collected after computing id(a.test)
because there aren't any references to it. (Note that you quote the documentation saying that an id is "unique and constant for this object during its lifetime" (emphasis mine).) b.test
happens to have the same id as the bound method you had before and it's allowed to because no other objects have the same id now.
Note that you should seldom use is
and even less often use id
. id(foo) == id(bar)
is always wrong.
Regarding your new example, hopefully you get what it does now:
>>> new_improved_test_method = lambda: None >>> a.test = new_improved_test_method >>> a.test is a.test True
In this case, we aren't making methods on the fly from functions on the class automatically binding self and returning bound method objects. In this case, you simply store a function as an instance attribute. Nothing special happens on lookup (descriptors only get called when you look up a class attribute), so every time you look up the attribute, you get the original object you stored.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With