Is and ID in Python

Source: Internet
Author: User

(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.bar

OUT[4]: False

In [5]: id (foo.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)

Ten store_slice+1

Slice+2

Delete_subscr

Delete_subscr

Slice+2

10340 Build_map

print_expr

11887 Jump_if_false_or_pop

Delete_global 29281 (29281)

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

print_expr

11887 Jump_if_false_or_pop

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

That's 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. An integer (or long

Integer) which is guaranteed to being unique and constant for the This object

During its lifetime. Objects with non-overlapping lifetimes

Have the same ID () value.

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.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.