После погружения в исходный код 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
в ast
PyInt_Object
два разных PyInt_Object
(фактически это выполнялось в функции ast_for_atom()
), но позже они объединяются.
Мне трудно понять источник в PyAST_Compile
и PyEval_EvalCode
, поэтому я здесь, чтобы попросить о помощи, я буду признателен, если кто-нибудь даст подсказку?