解释器维护的整数缓存是怎么回事?
在探索 Python 的源代码后,我发现了一个维护的 PyInt_Object 数组,范围从 int(- 5) 到 int(256) (@src/Objects/intobject.c).
运行一个小测试证明了这一点:
>>> a = 1 >>> b = 1 >>> a is b True >>> a = 257 >>> b = 257 >>> a is b False
但是,当在 py 文件中一起运行这些命令时或者用分号连接它们,结果更改:
>>> a = 257; b = 257; a is b True
为了理解为什么这两个整数仍然引用同一个对象,我深入研究了语法树和编译器,并发现了以下调用层次结构:
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()
然后我将调试代码集成到 PyInt_FromLong 和 PyAST_FromNode 之前/之后,然后运行test.py 脚本:
a = 257 b = 257 print "id(a) = %d, id(b) = %d" % (id(a), id(b))
输出为:
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
这表明在 cst 期间生成了两个单独的 PyInt_Object到 ast 转换(在 ast_for_atom() 中执行);
我发现 PyAST_Compile 和 PyEval_EvalCode 中的源代码难以理解,因此我寻求帮助。有人可以提供任何见解吗?
以上是为什么 Python 的整数缓存行为会根据代码的执行方式而变化?的详细内容。更多信息请关注PHP中文网其他相关文章!