Home >Backend Development >Python Tutorial >Why does the `is` operator behave differently with large integers inside and outside functions in Python?

Why does the `is` operator behave differently with large integers inside and outside functions in Python?

DDD
DDDOriginal
2024-11-01 15:31:02905browse

Why does the `is` operator behave differently with large integers inside and outside functions in Python?

Is Operator's Unexpected Behavior with Large Integers in Functions


When experimenting with Python's interpreter, a curious discrepancy was discovered regarding the is operator.

When the evaluation is performed within a function, it returns True, but when it's done externally, the result is False.

<br>def func():</p>
<pre class="brush:php;toolbar:false">a = 1000
b = 1000
return a is b

a = 1000
b = 1000
a is b, func()
>(False, True)

Since the is operator assesses the object's ids, this indicates that within the func function, a and b refer to the same integer instance, whereas outside the function, they refer to distinct objects.

Explanation


As the reference manual notes:


A block is a piece of Python program text that is executed as a unit.
The following are blocks: a module, a function body, and a class definition.
Each command typed interactively is a block.


Hence, in a function, a single code block holds a single numeric literal object, such as 1000, resulting in True for id(a) == id(b).

In the second instance, separate code objects exist, each with its numeric literal for 1000, causing id(a) != id(b).

Importantly, this behavior is not exclusive to integer literals; comparable results are observed with float literals (cf. here).

Remember to utilize the equality operator (==) for comparing objects, never the identity operator (is).

This knowledge pertains to CPython, Python's primary implementation. Alternative implementations may exhibit varying behavior.

Code Analysis


For comprehension, let's verify this behavior using code object analysis.

Function func:

Function objects have a code attribute that reveals the compiled bytecode. dis.code_info presents this data succinctly:

<br>print(dis.code_info(func))<br>Name:              func<br>Filename:          <stdin><br>Argument count:    0<br>Kw-only arguments: 0<br>Number of locals:  2<br>Stack size:        2<br>Flags:             OPTIMIZED, NEWLOCALS, NOFREE<br>Constants:<br>   0: None<br>   1: 1000<br>Variable names:<br>   0: a<br>   1: b<br>

The Constants entry shows that the constants are None (always present) and 1000. Thus, there's one int instance representing 1000. a and b reference this one object.

Interactive commands:

Each command is a code block that is parsed, compiled, and evaluated independently:

<br>com1 = compile("a=1000", filename="", mode="single")<br>com2 = compile("b=1000", filename="", mode="single")<br>

The code object for each assignment looks similar, but crucially, com1 and com2 have separate int instances for 1000, leading to False for id(com1.co_consts[0]) == id(com2.co_consts[0]).

Different code objects, distinct contents.

Caveats

  • Chained Statements: Evaluating a = 1000; b = 1000 yields True identity, since these chained assignments compile into one code block, producing one instance of 1000.


  • Module Level: Execution at the module level (indicated by the reference manual) also yields True due to a single code object.


  • Mutable Objects: Identity checks fail for mutable objects unless explicitly initialized to the same object (e.g., a = b = []).

  • The above is the detailed content of Why does the `is` operator behave differently with large integers inside and outside functions in Python?. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn