それが期待されていない場合にpythonで呼び出されるメソッド__del__

StackOverflow https://stackoverflow.com/questions/1935153

  •  20-09-2019
  •  | 
  •  

質問

私のpythonに新しいですし、Swaroop CHの「パイソンのバイト」の例を挙げて取り組んできました。私は私を不可解さ__del__方法でいくつかの行動を見ています。

基本的に、私は(Pythonの2.6.2で)次のスクリプトを実行している場合

class Person4:
    '''Represents a person'''
    population = 0

    def __init__(self, name):
        '''Initialize the person's data'''
        self.name = name
        print 'Initializing %s'% self.name

        #When the person is created they increase the population
        Person4.population += 1

    def __del__(self):
        '''I am dying'''
        print '%s says bye' % self.name

        Person4.population -= 1

        if Person4.population == 0:
            print 'I am the last one'
        else:
            print 'There are still %d left' % Person4.population


swaroop = Person4('Swaroop')
kaleem = Person4('Kalem')

のPythonコンソール(またはスパイダーインタラクティブコンソール)を使用して、私は次を参照してください。

  
    
      

execfileを(u'C:\ 1_eric \ Pythonの\ test1.py ')
      Swaroop
の初期化       初期化Kalem

             

execfileを(u'C:\ 1_eric \ Pythonの\ test1.py ')
      Swaroop
の初期化       Swaroopはさようなら言う
      私は最後の1
ています       Kalem
の初期化       Kalemはさようなら言う
      私は最後の一人です。

    
  

なぜセカンドランで__del__た直後に呼び出される__init__方法です?
私は、同じインスタンス名(「swaroop」と「kaleem」)ので、それが元のインスタンスを解放して、ゴミがそれを集めることに使用されていることを推測しています。しかし、これは現在の人口数で大混乱を演奏しているようです。

ここで何が起こっている?
混乱のこの種のを避けるための良い方法は何ですか?
   __del__の使用は避けてください?    それらを再利用する前に、既存のインスタンス名を確認しますか?    ...

おかげで、 エリック

役に立ちましたか?

解決

一般アドバイス:Pythonで__ __デルを使用しないでください。これは、ESP、いくつかの方法でガベージコレクションを破ることができます。オブジェクト間の循環参照の場合

グローバル変数の再定義 - ベストプラクティスではありません -

あなたの例では、execfileをの使用()に関連するさまざまな問題があります。あなたは本当に疑似デストラクタ(オブジェクトがガベージコレクトを取得するたびに呼び出されるつまりコード)を作成する必要がある場合はところで、いわゆる「ファイナライザ」関数を書く(それが適切にデストラクタではありません)とweakrefを使用して、それを呼び出します.REFコールバック。それはもちろんのインスタンスメソッドであること、およびコールバックで自己への参照を漏洩しないことを確認し、したがって、ラムダは実際にクロージャを作成することを覚えていないはずです!あなたが破壊されたインスタンスからのデータが必要な場合は、それ以外の場合は動作しません。

、ちょうどラムダ内部の「自己」を参照するの を決して必ず、FUNCのデフォルト引数のアプローチを使用します
from weakref import ref
from time import sleep

class Person4:
    '''Represents a person'''
    population = 0

    def __init__(self, name):
        '''Initialize the person's data'''
        self.name = name
        print 'Initializing %s'% self.name

        #When the person is created they increase the population
        Person4.population += 1

        self._wr = ref(self, lambda wr, name=self.name: Person4_finalizer(name))

def Person4_finalizer(name):
        '''I am dying'''
        print '%s says bye' % name

        Person4.population -= 1

        if Person4.population == 0:
            print 'I am the last one'
        else:
            print 'There are still %d left' % Person4.population

p1 = Person4("one")
p2 = Person4("two")
p3 = Person4("three")

del p2
del p3
sleep(5)

出力(睡眠は何が起こっているか見るのを助けるためにそこにある):

Initializing one
Initializing two
Initializing three
two says bye
There are still 2 left
three says bye
There are still 1 left
one says bye
I am the last one

他のヒント

ここで起こって物事のカップルがあります。あなたのPerson4クラスがインスタンス化されると、それはあなたのインタラクティブコンソールから0にそのpopulationクラス変数を初期化、あなたの「test1.py」ファイルを複数回実行しているように見えます。あなたはそれを実行して二回目は、Person4クラスは、それが技術的に可能どの再び宣言されているの異なるの最初のもの(それは同じ名前を持つにもかかわらず)から。つまり、独自の独立したpopulation数を有することを意味する。

さて、swaroopkaleemであるのグローバルの変数、 "test1.py" の両方のあなたのインスタンス間で共有。 Pythonは内部的に自動ガベージコレクションのほとんどのための参照カウントを使用していますので、最初Person4クラスの元のインスタンスはswaroopする2番目の割り当てまで解放されません。 swaroopに割り当てると、参照カウントが現在ゼロであるため__del__が呼び出される原因と、最初のインスタンスの参照カウントをデクリメントします。 の前ののインスタンスは、それが代わりに古いPerson4人口数の、の新しい__del__()・カウントをデクリメント消える。Person4.population内の名前でPerson4に言及しているので、 >

の意味を作っうまくいけば。これは、Pythonを学ぶ誰かに混乱するかもしれませんなぜ私が見ることができます。 Person4を使用してexecfile()クラスを再定義すると同時に、クラス変数の使用はさらに混乱を招く問題です。何が価値があるために、私は、Pythonのコードの多くを書いたと私は私が今まで__del__特別なメソッドを使用するために必要なてきたとは思わない。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top