(Ob1isob2) is equivalent to (id (ob1) id (ob2). First, the id function obtains the memory address of the object. if the memory addresses of the two objects are the same, then these two objects must be one object. Is equivalent to is. Python source code. (Ob1 is ob2) is equivalent to (id (ob1) = id (ob2 ))
First, the id function can obtain the object's memory address. if the two objects have the same memory address, the two objects must be one object. Is equivalent to is. Python source code.
static PyObject * cmp_outcome(int op, register PyObject *v, register PyObject *w){ int res = 0; switch (op) { case PyCmp_IS: res = (v == w); break; case PyCmp_IS_NOT:res = (v != w); break;
But how can this problem occur with the code below?
In [1]: def bar(self, x):...: return self.x + y...: In [2]: class Foo(object):...: x = 9...: def __init__(self ,x):...: self.x = x...: bar = bar...: In [3]: foo = Foo(5)In [4]: foo.bar is Foo.barOut[4]: FalseIn [5]: id(foo.bar) == id(Foo.bar)Out[5]: True
The two objects are judged to be False by "is" and True by id ", which is inconsistent with the known facts. how can we explain this phenomenon? The best solution to this problem is to call the dis module to see what the two comparison statements have done.
In [7]: dis.dis("id(foo.bar) == id(Foo.bar)") 0 BUILD_MAP 10340 3 BUILD_TUPLE 28527 6 <46> 7 DELETE_GLOBAL 29281 (29281) 10 STORE_SLICE+1 11 SLICE+2 12 DELETE_SUBSCR 13 DELETE_SUBSCR 14 SLICE+2 15 BUILD_MAP 10340 18 PRINT_EXPR 19 JUMP_IF_FALSE_OR_POP 11887 22 DELETE_GLOBAL 29281 (29281) 25 STORE_SLICE+1 In [8]: dis.dis("foo.bar is Foo.bar") 0 BUILD_TUPLE 28527 3 <46> 4 DELETE_GLOBAL 29281 (29281) 7 SLICE+2 8 BUILD_MAP 8307 11 PRINT_EXPR 12 JUMP_IF_FALSE_OR_POP 11887 15 DELETE_GLOBAL 29281 (29281)
The actual situation is when execution. actually, a proxy object, foo. bar is Foo. when bar is used, the two objects are generated sequentially and put in the stack for comparison. because the addresses are different, it must be False, but id (foo. bar) = id (Foo. bar. bar, and then calculate foo. the address of bar. after calculation, foo. after the address of bar, no object points to foo. bar, so foo. the bar object will be released. Then generate Foo. bar object, because foo. bar and Foo. bar uses the same memory size, so it just re-uses the original foo. bar memory address, so id (foo. bar) = id (Foo. bar) is True.
The following content is provided by Leo Jay Daniel, who explained it more transparently.
It is a problem to use id (expression a) = id (expression B) to determine whether the results of two expressions are the same object.
Foo. bar is called attribute reference [1]. it is a type of expression. Foo is an instance object and bar is a method. in this case, the result returned by the expression foo. bar is method object [2]. According to the document:
When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object.
Foo. bar itself is not a simple name, but the calculation result of the expression. it is a method object in id (foo. bar) in such an expression, method object is just a temporary intermediate variable, and it makes no sense to do id for the temporary intermediate variable.
A more obvious example is,
print id(foo.bar) == id(foo.__init__)
The output result is also True.
See id document [3]:
Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value. CPython implementation detail: This is the address of the object in memory.
Only when you can ensure that the object will not be destroyed can you use IDs to compare two objects. Therefore, if you have to compare it, you have to write it like this:
fb = foo.bar Fb = Foo.bar print id(fb) == id(Fb)
That is, bind the results of the two expressions to the name, and then compare whether the results are the same object to get the correct results.
The is expression [4] is the same. you get the correct result because CPython's current implementation details are determined. The current implementation of is to calculate the objects on both sides of the left and right, and then compare whether the addresses of these two objects are the same. If you change it to another day, first calculate the left side, save the address, release the left side, and then calculate the right side. then, if you compare it, your is result may be wrong. This issue is also mentioned in the official document [5]. In my opinion, the correct method is also like id. First, calculate both the left and right sides, explicitly bind them to their respective names, and then use is to judge.
[1] http://docs.python.org/2/reference/expressions.html#attribute-references
[2] http://docs.python.org/2/tutorial/classes.html#method-objects
[3] http://docs.python.org/2/library/functions.html#id
[4] http://docs.python.org/2/reference/expressions.html#index-68
[5] http://docs.python.org/2/reference/expressions.html#id26
The above is the details about the is and id in Python. For more information, see other related articles in the first PHP community!