The integer Python solution is more detailed

  • 2020-05-30 20:26:43
  • OfStack

preface

In Python, all 1 slices are objects, and without exception, integers are also objects. The comparison between objects can be done with == or is.

The difference between == and is operations is:

is compares whether the id values of two objects are equal, that is, whether the two objects are the same instance object and point to the same memory address. == compares the contents of two objects to be equal. By default, the object will be called __eq__() Methods.

Once you know the difference between is and ==, you may encounter the following confusion, so here is an article that tries to put out some obscure things in Python in the hope that it will help you.

Let's look at two pieces of code first:

Section 1:


>>> a = 256
>>> b = 256
>>> a == b
True
>>>

Section 2:


>>> a = 256
>>> b = 256
>>> a is b
True
>>>

It is easy to understand that a==b returns True in snippet 1, since the value of both objects is 256. For fragment 2, a is b also returns True, which means that a and b point to the same object. You can check whether their id values are equal to each other:


>>> id(a)
8213296
>>> id(b)
8213296
>>> 

It turned out that they were indeed the same object, pointing to the same memory address. Is it true that all integer objects are the same instance object as long as their values (contents) are the same? In other words, for integer objects as long as == returns True, will the is operation also return True?

Take a look at the following two pieces of code with that in mind:

Section 1:


>>> a = 257
>>> b = 257
>>> a == b
True
>>>

Section 2:


>>> a = 257
>>> b = 257
>>> a is b
False
>>>

For 257, a is b returns False, which may or may not come as a surprise, but we're going to get to the bottom of the matter anyway.

Doubt 1

Out of consideration for the performance, Python internal optimization of did a lot of work, for integer object, Python more frequent use of the integer object caching, saved to a chain table, called small_ints in Python throughout the life cycle, no need to refer to these integer object, no longer create a new object, but a direct reference to the object in the cache. Python places those small objects in the range [-5, 256] that are likely to be used frequently into small_ints, but whenever small integers are needed, it takes them from there instead of creating new objects temporarily. Since 257 is no longer in the range of small integers, a and b exist as two separate objects within Python, each of which does not interfere with each other, although they have a value of 1.

Now that we understand the first question, let's go ahead and write a function on the Python interactive command line and look at the following code:

Section 1:


>>> c = 257
>>> def foo():
...  a = 257
...  b = 257
...  print a is b
...  print a is c
... 
>>> foo()
True
False

Well, what happens? Yes, you read that right. In the code in fragment 1, a is b returns True, while a is c returns False, a, b, c both return False, a, b, c both return False, a a, b, c both return True, and a is c return False, a a, b, c all return 257. Is that a complete rejection of the knowledge that was built so easily, and what's going on in this code? Is the conclusion in puzzle # 1 wrong?

To reassure 2

A Python program is from code blocks A block is a Python __eq__() program that is a unit The following are blocks: a module, a function body, and a class definition. Each command interactively is a file input to to interpreter or specified as command argument to the interpreter with the '-c' option) is a code block. structure of a program

In order to understand this, it is necessary to understand the concept of a block of program code. The Python program consists of code blocks that are executed as one of the smallest basic units of the program. A single line of code in a module file, a function body, a class, and an interactive command is called a code block. In the code above, it consists of two code blocks, c = 257 as one, and the function foo as the other. In order to further improve the performance of Python, whenever an integer object is created in a code block, if an object with the same value exists in the code block, it is directly referred to, otherwise a new object is created. For performance reasons, Python does not create immutable objects in the same code block unless they have the same value. Instead, it directly refers to existing objects. Therefore, not only integer objects, but also string objects follow the same principle. Therefore, a is b naturally returns True, while c and a are not in the same code block, so two objects with values of 257 are created inside Python. To verify our conclusion, we can take a look at this code from a bytecode perspective using the dis module.


>>> import dis
>>> dis.dis(foo)
 2   0 LOAD_CONST    1 (257)
    3 STORE_FAST    0 (a)

 3   6 LOAD_CONST    1 (257)
    9 STORE_FAST    1 (b)

 4   12 LOAD_FAST    0 (a)
    15 LOAD_FAST    1 (b)
    18 COMPARE_OP    8 (is)
    21 PRINT_ITEM   
    22 PRINT_NEWLINE  

 5   23 LOAD_FAST    0 (a)
    26 LOAD_GLOBAL    0 (c)
    29 COMPARE_OP    8 (is)
    32 PRINT_ITEM   
    33 PRINT_NEWLINE  
    34 LOAD_CONST    0 (None)
    37 RETURN_VALUE

You can see that both 257s are obtained from the same location of the constant pool, co_consts[1].

conclusion

After a long speech, I came to two conclusions:

1. The small integer object [-5,256] is reused within the scope of the global interpreter and will never be recycled by GC.

2. Immutable objects in the same code block will not be created repeatedly as long as the values are the same. It doesn't seem like these things are going to help you in your daily work, because you won't be using is to compare the values of two integer objects. So why bring it up? Well, programmers learn knowledge, should not be dabbled in, to give full play to the spirit of the end.


Related articles: