3

オブジェクト クラスのすべての新しいインスタンスを収集する静的リストを使用してクラスを作成しようとしています。私が直面している問題は、たとえば整数と同じようにリストを使用しようとするとすぐに、魔法のマーカーを使用できなくなったよう__del__です。

私の例:

class MyClass(object):  

    count = 0
    #instances = []

    def __init__(self, a, b):
        self.a = a
        self.b = b
        MyClass.count += 1
        #MyClass.instances.append(self)

    def __str__(self):
        return  self.__repr__()

    def __repr__(self):
        return "a: " + str(self.a) + ", b: " + str(self.b)

    def __del__(self):
        MyClass.count -= 1
        #MyClass.instances.remove(self)

A = MyClass(1,'abc')
B = MyClass(2,'def')
print MyClass.count
del B
print MyClass.count

コメントを使用すると、正しい答えが得られます。

2
1

しかし、コメントがなければ、静的オブジェクト リスト MyClass.instances を含めて、間違った答えが得られます。

2
2

__del__MyClass がそのメソッドにアクセスできなくなったようです。どうして?

4

4 に答える 4

4

ドキュメントから、

del x doesn’t directly call x.__del__() — the former decrements the reference
count for x by one, and the latter is only called when x‘s reference count
reaches zero. 

コメントを外すと、

instances = []
...
...
MyClass.instances.append(self)

に現在のオブジェクトへの参照を保存していMyClass.instancesます。つまり、参照カウントは内部で 1 ずつインクリメントされます。そのため__del__、すぐには呼び出されません。

この問題を解決するには、次のようにリストから項目を明示的に削除します

MyClass.instances.remove(B)
del B

これで印刷されます

2
1

予想通り。

この問題を解決する方法がもう 1 つあります。それは使用することweakrefです。ドキュメントから、

オブジェクトへの弱参照は、オブジェクトを存続させるのに十分ではありません: 参照先への残りの参照が弱参照のみの場合、ガベージ コレクションは自由に参照先を破棄し、そのメモリを別のものに再利用します。弱い参照の主な用途は、大きなオブジェクトを保持するキャッシュまたはマッピングを実装することです。この場合、大きなオブジェクトがキャッシュまたはマッピングに表示されるという理由だけで存続させたくない場合に使用します。

そのため、 willを持っていてweakrefもオブジェクトの削除は延期されません。でweakref、これはこのように修正できます

MyClass.instances.append(weakref.ref(self))
...
...
# MyClass.instances.remove(weakref.ref(self))
MyClass.instances = [w_ref for w_ref in MyClass.instances if w_ref() is None]

メソッドを使用する代わりに、各オブジェクトをremove呼び出すことができ、それらが を返す場合、それらは既に死んでいます。そのため、リスト内包表記でそれらを除外します。weakrefNone

したがって、今、あなたが を言うとき、のためにs が存在しdel Bていても、それは呼び出します(代入を行うなどして、同じオブジェクトを指す他の変数を作成していない限り)。weakrefB__del__

于 2014-01-15T10:49:05.060 に答える
1

http://docs.python.org/2.7/reference/datamodel.html#basic-customizationから引用します( の後の灰色の段落object.__del__):

del xは直接呼び出しませんx.__del__()— 前者は x の参照カウントを 1 減らし、後者は x の参照カウントがゼロに達したときにのみ呼び出されます。

ここで呼び出しますdel Bが、MyClass.instances にはまだ B のインスタンスが存在するため、B は引き続き参照され、破棄されないため、__del__関数は呼び出されません。直接呼び出すB.__del__()と機能します。

于 2014-01-15T10:48:52.723 に答える