5

これは、Python で参照カウントがどのように機能するかをよりよく理解するための試みです。

クラスを作成してインスタンス化しましょう。インスタンスの参照カウントは次のようになります( は1、そのクラス インスタンスを参照する独自の内部構造であるため、参照カウントが だけ増加します):getrefcount21

>>> from sys import getrefcount as grc
>>> class A():
    def __init__(self):
        self.x = 100000


>>> a = A()
>>> grc(a)
2

aの内部変数xには2参照があります:

>>> grc(a.x)
3

とのメソッドaによって参照されることを期待していました。それから私はチェックすることにしました。A__init__

そのため、変数にアクセスできるようにするためだけにb、名前空間に一時変数を作成しました。それは(予想どおり)になるために参照番号を増やしました:__main__x13

>>> b = a.x
>>> grc(a.x)
4

次に、クラス インスタンスを削除すると、ref カウントが次のように減少しました1

>>> del a
>>> grc(b)
3

だから今、2参照があります:1つはbybで、もう1つはbyですA(私が予想したように)。

A名前空間から削除する__main__ことで、カウントが1再び減少することを期待しています。

>>> del A
>>> grc(b)
3

しかし、それは起こりません。を参照できるクラスAまたはそのインスタンスはありませんが、名前空間100000以外の何かによって参照されています。b__main__

だから、私の質問は、何100000から離れて参照されているのbですか?


BrenBarnobject()は、内部のどこかに格納されている可能性のある数値の代わりに使用することを提案しました。

>>> class A():
    def __init__(self):
        self.x = object()


>>> a = A()
>>> b = a.x
>>> grc(a.x)
3
>>> del a
>>> grc(b)
2

インスタンスを削除した後、非常に論理的なa参照が 1 つだけありました。b

理解するために残されている唯一のことは、 number ではそうではない理由100000です。

4

2 に答える 2

3

a.xは整数 10000 です。この定数は、 の__init__()メソッドに対応するコード オブジェクトによって参照されますA。コード オブジェクトには常に、コード内のすべてのリテラル定数への参照が含まれます。

>>> def f(): return 10000
>>> f.__code__.co_consts
(None, 10000)

この線

del A

名前のみを削除Aし、 の参照カウントを減らしますA。Python 3.x では (ただし 2.x ではそうではありません)、クラスには循環参照が含まれることが多いため、明示的にガベージ コレクターを実行した場合にのみガベージ コレクションが行われます。そして実際に、

import gc
gc.collect()

afterdel Aは の参照カウントの削減につながりますb

于 2012-06-03T22:48:35.057 に答える
2

これは、整数をテスト値として使用した結果である可能性があります。Python は、不変であるため、後で再利用するために整数オブジェクトを保存することがあります。self.x = object()代わりに (常に x の新しいオブジェクトを作成する) を使用してコードを実行するgrc(b)==2と、最後に取得します。

于 2012-06-03T22:46:28.747 に答える