Python のソース コードを調べてみると、から(@src/Objects/intobject.c)PyInt_Object
までの s の配列が保持されていることがわかりました。int(-5)
int(256)
ちょっとした実験がそれを証明しています:
>>> 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
次に、 inと before/after にデバッグ コードを追加し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
toast
変換中に 2 つPyInt_Object
の異なる が作成される (実際にはast_for_atom()
関数内で実行される) が、後でマージされることを意味します。
PyAST_Compile
とのソースを理解するのは難しいと思うPyEval_EvalCode
ので、助けを求めるためにここにいます。