異なる参照カウントを生成するシナリオがいくつかあります。最も簡単にはREPLコンソールです:この結果を理解する
>>> import sys
>>> the_var = 'Hello World!'
>>> print(sys.getrefcount(the_var))
2
は非常に簡単です - The count returned is generally one higher than you might expect
- 1つのローカルスタック内の参照とsys.getrefcount()
機能(さえdocumentationはそれについて警告に別の一時/ローカルがあります)。スタンドアロンスクリプトとして実行するときしかし:あなたが気づいたよう
import sys
the_var = 'Hello World!'
print(sys.getrefcount(the_var))
# 4
、あなたは4
を取得します。だから何を与える?
>>> import gc
>>> the_var = 'Hello World!'
>>> gc.get_referrers(the_var)
[{'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'the_var': 'Hello
World!', 'gc': <module 'gc' (built-in)>, '__name__': '__main__', '__doc__': None}]
ませ不思議が、 - それは、本質的に単に現在のネームスペースです:私たちはREPLコンソールでそれを実行していない場合はそう - gc
モジュール - まあ、ガベージコレクタに非常に有用インターフェースがあります...調査することができます(locals()
)は、他の場所には存在しません。
import gc
import pprint
the_var = 'Hello World!'
pprint.pprint(gc.get_referrers(the_var))
これは(YMMV、あなたのPythonのバージョンに基づく)を出力します:
[['gc',
'pprint',
'the_var',
'Hello World!',
'pprint',
'pprint',
'gc',
'get_referrers',
'the_var'],
(-1, None, 'Hello World!'),
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'test.py',
'__name__': '__main__',
'__package__': None,
'gc': <module 'gc' (built-in)>,
'pprint': <module 'pprint' from 'D:\Dev\Python\Py27-64\lib\pprint.pyc'>,
'the_var': 'Hello World!'}]
案の定、我々はリストに2つの参照を持っている私たちは、スタンドアロンスクリプトとしてという実行したときはどうなりますsys.getrefcount()
が私たちに語ったのと同じように、それらは何ですか?さて、Pythonインタプリタがあなたのスクリプトを解析しているときには、最初にcompileバイトコードにする必要があります。そして、それが実行されている間は、変数にも言及しているため、参照として宣言されているリストにすべての文字列を格納します。
もう1つの潜在的なエントリ((-1, None, 'Hello World!')
)はpeep-hole optimizerから来ており、アクセス(この場合は文字列参照)が最適化されています。これらの
の両方が純粋に一時的なオプションである - あなたの現在のコンテキストから、あなたのコンパイル「を外部委託」していた場合は、これらの参照が表示されないので、REPLコンソールは、コンテキスト分離を行っている。
import gc
import pprint
exec(compile("the_var = 'Hello World!'", "<string>", "exec"))
pprint.pprint(gc.get_referrers(the_var))
あなたは「取得dは:
import sys
exec(compile("the_var = 'Hello World!'", "<string>", "exec"))
print(sys.getrefcount(the_var))
# 2
:
[{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'test.py',
'__name__': '__main__',
'__package__': None,
'gc': <module 'gc' (built-in)>,
'pprint': <module 'pprint' from 'D:\Dev\Python\Py27-64\lib\pprint.pyc'>,
'the_var': 'Hello World!'}]
を、あなたはsys.getreferencecount()
経由で参照カウントを得ることで、元の試みに戻っていた場合
REPLコンソールのように、まるで期待通りです。ピープホールの最適化による余分な参照は、内部で発生するため、参照を数える前にガベージコレクション(gc.collect()
)を強制してすぐに破棄することができます。
ただし、コンパイル時に作成される文字列リストは、ファイル全体が解析されてコンパイルされるまで解放することはできません。そのため、別のスクリプトでスクリプトをインポートしてから参照番号をthe_var
)
これを直接pythonまたはipythonシェルに入力していませんか?
3
の代わりに4
の代わりになるでしょう。またはスタンドアロンスクリプトとして実行していますか?私は単純なPythonシェルで2つの参照を取得します。 – Meitham私はあなたのコードを2.7.13で実行すると 'Var created:2 references'を取得します。 – Alex
私は対話モードでは2つの参照を、スクリプトでは3つ(コードオブジェクトの定数からの参照のために1つ)を追加する予定ですが、別の参照を作成することがあります。 – user2357112