(Ob1 is OB2) equivalent to (ID (ob1) = = ID (ob2))
First the ID function can get the memory address of the object, if the memory address of the two objects is the same, then the two objects must be an object. is equivalent to IS. Python source code is proof.
Static Pyobject * cmp_outcome (int op, register pyobject *v, register pyobject *w) {int res = 0; switch (OP) {case Pycmp_i S: res = (v = = W), break, Case pycmp_is_not:res = (v! = W); break;
But look at the code below, how does this happen?
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 (f Oo.bar) = = ID (foo.bar) out[5]: True
Two objects are judged by is false, but the ID is true, which is inconsistent with the facts we know, how to explain this phenomenon? The best solution to this situation 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) store_ Slice+1 slice+2 DELETE_SUBSCR DELETE_SUBSCR slice+2 Build_map 10340 print_expr 11887 jump_if_false_or_pop Delete_global 2 9281 (29281) store_slice+1 in [8]: Dis.dis ("Foo.bar is Foo.bar") 0 build_tuple 28527 3 & Lt;46> 4 Delete_global 29281 (29281) 7 slice+2 8 Build_map 8307 print_expr jump_if_false_or_pop 11887 delete_global 29281 (29281)
The real situation is when executing the. operator when the actual is generated a proxy object, Foo.bar is Foo.bar time, two object order generation, placed in the stack compared, because the address is different is certainly false, but the ID (foo.bar) = = ID (foo.bar) The time is different, first generate Foo.bar, and then calculate the address of foo.bar, after calculating the foo.bar address, there is no object to Foo.bar, so the Foo.bar object will be released. The Foo.bar object is then generated, because the memory size used by Foo.bar and Foo.bar is the same, so the memory address of the original foo.bar is reused, so the result of the ID (foo.bar) = = ID (foo.bar) is true.
The following content is provided by mail Leo Jay Daniel, who explains the more transparent.
It is problematic to use the ID (expression a) = = ID (expression b) to determine that the result of two expressions is not the same object.
Foo.bar This form is called attribute reference [1], which is one of the expressions. Foo is a instance Object,bar is a method, and this time the expression foo.bar returns the result called Method Object [2]. According to the documentation:
When an instance attribute was referenced that isn ' t a data attribute, it class is searched. If the name denotes a valid class attribute a function object, a method object is created by packing (pointers to) The instance object and the function object just found together in a abstract Object:this is the method object.
Foo.bar itself is not a simple name, but the expression of the result, is a method object, in the ID (foo.bar) Such an expression, method object is only a temporary intermediate variable, do not have the meaning of the temporary intermediate variable ID.
A more obvious example is that
Print ID (foo.bar) = = ID (foo.__init__)
The result of the output is also true
Look at the ID of the document [3]:
Return the "Identity" of an object. The is a integer (or long Integer) which is guaranteed to being unique and constant for the this object during its lifetime. The same ID () value is objects with non-overlapping lifetimes. CPython implementation Detail:this is the address of the object in memory.
Only if you can guarantee that the object will not be destroyed, you can compare two objects with an ID. So, if you have to be more than that, you have to write:
FB = foo.bar FB = foo.bar Print ID (FB) = = ID (FB)
You can get the correct result by binding the result of two expressions to the name and then to the same object.
The IS expression [4] is also the same, you now get the correct result, completely because the implementation details of the CPython now decided. The current is implementation, is the left and right sides of the object are calculated, and then compare the two objects are the same address. In case one day change to, first count left, save the address, left off, then the right side, then compare, your is the result may be wrong. [5] The issue is also mentioned in the official documentation. I think the right way is also like ID, first the left and right sides are computed, and explicitly bound to their 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