Detail the is operator in python

  • 2020-06-19 10:57:03
  • OfStack

You can verify with the == operator in Java to deepen your understanding of references and objects. Original question: Why does Python run the same statement directly as it does on the command line but with different results? Do they have different caching mechanisms?

In fact, the high ticket answer has been very detailed. I just want to add one more thing.

The is operator is one of the built-in operators of the Python language. It compares whether two variables point to the same object.

The difference between == and


class A():
 def __init__(self, v): 
  self.value = v
 def __eq__(self, t): 
  return self.value == t.value
a = A(3)
b = A(3)
print a == b
print a is b

So this is True, False. Because we've rewritten the method with each ___ 16EN__ so that a, b, will compare only their value. As long as their value are equal, then a, b are equal.

The is operator determines whether two variables refer to the same object.

Same object?

is is pretty easy to use, but in practice, the difficulty lies in deciding which objects are the same.

Look at the following tests. Without looking at the results, how many did you get right?


a = 10
b = 10
print a is b
a = 10.0
b = 10.0
print a is b
a = 10
def f():
 return 10
print f() is a
a = 1000
def f():
 return 1000
print f() is a
a = 10.0
def f():
 return 10.0
print f() is a

Well. So this is True, True, True, False, False. Are you right?

There are two issues involved in this result: first, the caching of small integers, and second, the organization of CodeObject in pyc files.

Python caches one copy of -127 to 128. This is the same as the Integer class of Java. So, for integers between -127 and 128, there is only one instance in the entire Python virtual machine. Whenever you use is in any scenario, it will always be True, so we know that these two tests 1 must be True:


a = 10
b = 10
print a is b
a = 10
def f():
 return 10
print f() is a

Next, let's focus on these two tests:


a = 10.0
b = 10.0
print a is b
a = 10.0
def f():
 return 10.0
print f() is a

Why is one True and one False. To explore this, look at it from a bytecode perspective. Let's first compile this file 1:


python -m compileall testis.py

Then use this tool to view the following bytecode file:

https:// github.com/hinus/railgu n/blob/master/src/main/python/rgparser/show.py

The output is as follows:


 <argcount> 0 </argcount>
 <nlocals> 0</nlocals>
 <stacksize> 2</stacksize>
 <flags> 0040</flags>
 <code>
  6400005a00006400005a01006500006501006b080047486400005a000064
  01008400005a02006502008300006500006b0800474864020053
 </code>
 <dis>
 1   0 LOAD_CONST    0 (10.0)
    3 STORE_NAME    0 (a)

 2   6 LOAD_CONST    0 (10.0)
    9 STORE_NAME    1 (b)

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

 5   23 LOAD_CONST    0 (10.0)
    26 STORE_NAME    0 (a)

 6   29 LOAD_CONST    1 (<code object f>)
    32 MAKE_FUNCTION   0
    35 STORE_NAME    2 (f)

 8   38 LOAD_NAME    2 (f)
    41 CALL_FUNCTION   0
    44 LOAD_NAME    0 (a)
    47 COMPARE_OP    8 (is)
    50 PRINT_ITEM   
    51 PRINT_NEWLINE  
    52 LOAD_CONST    2 (None)
    55 RETURN_VALUE  
 </dis>
 <names> ('a', 'b', 'f')</names>
 <varnames> ()</varnames>
 <freevars> ()</freevars>
 <cellvars> ()</cellvars>
 <filename> 'testis.py'</filename>
 <name> '<module>'</name>
 <firstlineno> 1</firstlineno>
 <consts>
  10.0
  <code>
   <argcount> 0 </argcount>
   <nlocals> 0</nlocals>
   <stacksize> 1</stacksize>
   <flags> 0043</flags>
   <code> 64010053</code>
   <dis>
 7   0 LOAD_CONST    1 (10.0)
    3 RETURN_VALUE  
   </dis>
   <names> ()</names>
   <varnames> ()</varnames>
   <freevars> ()</freevars>
   <cellvars> ()</cellvars>
   <filename> 'testis.py'</filename>
   <name> 'f'</name>
   <firstlineno> 6</firstlineno>
   <consts>
   None
   10.0
   </consts>
   <lnotab> 0001</lnotab>
  </code>
  None
 </consts>
 <lnotab> 060106010b0206010902</lnotab>

Notice that the entire python file is actually one large file < code > Object, f corresponds to one function < code > Object, the code object as a whole is large < code > 1 const entry in the consts field of the object. Again, notice that at large < code > There's an const item like 10.0, and an f item like that < code > Object, there is also a 10.0 floating point number.

When python loads the file, the master completes < code > The floating-point number 10.0 in, generates 1 PyFloatObject. In other words, the constant scale of the static pyc file becomes the constant scale in memory after being loaded, and the 10.0 in the table of the file becomes one PyFloatObject in memory. So, a, b both variables refer to this PyFloatObject.

But what about the 10.0 in f? It is not really initialized until MAKE_FUNCTION is called. As the return value of the f method, it must be the same as the Lord we said earlier < code > 10.0 in is not the same object.

Essentially, this is a design flaw of Python (Java, for example, has 1 file as the compilation unit, and sharing the same constant pool alleviates the problem. The same problem occurs if the == operator is used across files. It still hasn't solved the problem. Actually, I don't know how to solve the problem myself. We should try to avoid this use of is. Always limit the use of is to the first example in this article. It's a little bit safer.


Related articles: