What's with the integer cache maintained by the interpreter?
After exploring Python's source code, I discovered an array of PyInt_Objects maintained, ranging from int(-5) to int(256) (@src/Objects/intobject.c).
Running a small test proves it:
>>> a = 1 >>> b = 1 >>> a is b True >>> a = 257 >>> b = 257 >>> a is b False
However, when running these commands together in a py file or joining them with semicolons, the result changes:
>>> a = 257; b = 257; a is b True
To understand why these two integers still reference the same object, I delved into the syntax tree and compiler and came across the following calling hierarchy:
PyRun_FileExFlags() mod = PyParser_ASTFromFile() node *n = PyParser_ParseFileFlagsEx() //source to cst parsetoke() ps = PyParser_New() for (;;) PyTokenizer_Get() PyParser_AddToken(ps, ...) mod = PyAST_FromNode(n, ...) //cst to ast run_mod(mod, ...) co = PyAST_Compile(mod, ...) //ast to CFG PyFuture_FromAST() PySymtable_Build() co = compiler_mod() PyEval_EvalCode(co, ...) PyEval_EvalCodeEx()
I then integrated debug code into PyInt_FromLong and before/after PyAST_FromNode, then ran a test.py script:
a = 257 b = 257 print "id(a) = %d, id(b) = %d" % (id(a), id(b))
The output is:
DEBUG: before PyAST_FromNode name = a ival = 257, id = 176046536 name = b ival = 257, id = 176046752 name = a name = b DEBUG: after PyAST_FromNode run_mod PyAST_Compile ok id(a) = 176046536, id(b) = 176046536 Eval ok
This indicates that two separate PyInt_Objects are generated during the cst to ast transformation (executed in ast_for_atom()); however, these objects are then amalgamated.
I found the source code in PyAST_Compile and PyEval_EvalCode challenging to understand, so I sought assistance. Can someone offer any insights?
The above is the detailed content of Why Does Python's Integer Cache Behavior Change Depending on How the Code is Executed?. For more information, please follow other related articles on the PHP Chinese website!