5

これをインタープリターに入力すると、「y」を呼び出すとデストラクタが呼び出されるように見えますか?

class SmartPhone:
    def __del__(self):
       print "destroyed"

y = SmartPhone()
y  #prints destroyed, why is that?
y  #object is still there

これは1回の実行です。出力は意味がありません。

C:\Users\z4>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> class SmartPhone:
...     def __del__(self):
...        print "destroyed"
...
>>> y = SmartPhone()
>>> del y
destroyed
>>> y = SmartPhone()
>>> y
<__main__.SmartPhone instance at 0x01A7CBC0>
>>> y
<__main__.SmartPhone instance at 0x01A7CBC0>
>>> y
<__main__.SmartPhone instance at 0x01A7CBC0>
>>> del y
>>> y = SmartPhone()
>>> y
destroyed
<__main__.SmartPhone instance at 0x01A7CB98>
>>>

もう1つは、「del y」を呼び出すと、デストラクタが呼び出される場合と呼び出されない場合があります

C:\Users\z4>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> class SmartPhone:
...     def __del__(self):
...             print "destroyed"
...
>>>
>>> y = SmartPhone()
>>>
>>> y
<__main__.SmartPhone instance at 0x01B6CBE8>
>>> y
<__main__.SmartPhone instance at 0x01B6CBE8>
>>> y
<__main__.SmartPhone instance at 0x01B6CBE8>
>>> del y
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> y = SmartPhone()
>>> y
destroyed
<__main__.SmartPhone instance at 0x01B6CC38>
>>> del y
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>>
4

5 に答える 5

15

問題の出力は、インタラクティブ シェルでのみ複製されます。

インタラクティブ セッションで_は、最後の値を参照する追加の変数が存在します。

sys.getrefcountを使用して参照カウントを調べる:

>>> import sys
>>> class SmartPhone:
...     def __del__(self):
...        print "destroyed"
...
>>> y = SmartPhone()
>>> sys.getrefcount(y) # not printed, _ does not reference SmartPhone object yet.
2
>>> y
<__main__.SmartPhone instance at 0x000000000263B588>
>>> sys.getrefcount(y) # y printed, _ reference SmartPhone object.
3

23上記の出力では、 、 である必要が1あり2ます。getrefcount のドキュメントに記載されているように、getrefcount() は一時的に参照カウントを増やすため、それらはそのように出力されます。


何が起こっているのかを簡単に調べられるように、スマートフォンを次のように変更しました。

>>> class SmartPhone(object):
...     def __init__(self, name):
...         self.name = name
...     def __repr__(self):
...         return super(SmartPhone, self).__repr__() + ' name=' + self.name
...     def __del__(self):
...        print "destroyed", self
...
>>> y = SmartPhone('first')
>>> del y # deleted immediately, because only "y" reference it.
destroyed <__main__.SmartPhone object at 0x00000000024FEFD0> name=first
>>> y = SmartPhone('second')
>>> y # at this time, _ reference to second y (y's reference count is now 2)
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second
>>> y
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second
>>> y
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second
>>> del y # not deleted immediately, because _ reference it.
>>> y = SmartPhone('third') # _ still reference the second y, because nothing is printed.
>>> y # second y is deleted, because _ now reference the third y. (no reference to the second y)
destroyed <__main__.SmartPhone object at 0x00000000024FEFD0> name=second
<__main__.SmartPhone object at 0x000000000264A470> name=third
于 2013-07-10T15:21:14.657 に答える
0

__del__C++ の意味でのデストラクタではありません。これは、オブジェクトが破棄される前、およびオブジェクトがガベージ コレクション可能になった後に実行されることが保証されているメソッドです。

CPython では、これは参照カウントが 0 に達したときに発生します。したがって、メソッドを持つオブジェクトを保持する単一の変数に値を再割り当てすると、__del__そのオブジェクトのそのメソッドはその後すぐに呼び出されます。

于 2013-07-10T15:20:11.797 に答える
0

@falsetru の回答を拡張して、何が起こっているのかを簡単に確認できるスマートフォンを次に示します。

myid = 0

class SmartPhone(object):
    def __init__(self):
        global myid
        self.myid = myid
        print("init %d" % self.myid)
        myid += 1
    def __del__(self):
        print("delete", self)
    def __repr__(self):
        return "repr %d" % self.myid
    def __str__(self):
        return "str %d" % self.myid

>>> 
>>> y=SmartPhone()
init 0
>>> # _ will hold a ref to y
... 
>>> 
>>> y
repr 0
>>> _
repr 0
>>> # del only decreases the ref count
... 
>>> del y
>>> _
repr 0
>>> # _ still refs 0
... 
>>> y=SmartPhone()
init 1
>>> # but now i reassign _ and 0 goes away
... 
>>> y
delete str 0
repr 1
>>> 
于 2013-07-10T16:04:30.313 に答える