For example, the usage of is and id in Python

Source: Internet
Author: User
This article mainly introduces the usage of is and id in Python, which is the basic knowledge in Python learning. The author provides an example to briefly explain how to use it. For more information, see (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]: False In [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.barFb = Foo.barprint 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.

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.