问题描述:

When trying to understand some Python concepts, I encountered the following problem :

class A:

def __init__(self, x):

self.x = x

def __del__(self):

print("del")

a1 = A()

outputs :

$ python test.py

del

Traceback (most recent call last):

File "testdest.py", line 9, in <module>

a1 = A()

TypeError: __init__() takes exactly 2 arguments (1 given)

The error is obvious (missing argument when instantiating), but I wonder why the destructor is called before having an instance?

Unless that when trying to instantiate, Python creates a sort of instance even before calling the constructor and that will need to be cleaned at the end?

Since self is passed to the constructor, Can I assume this self is the instance? It that's true, then the instance already exists when calling the constructor, is that right?

Is this a behaviour of the garbage collector that may depend of the current implementation?

网友答案:

From the Python documentation:

Objects are never explicitly destroyed; however, when they become unreachable they may be garbage-collected. An implementation is allowed to postpone garbage collection or omit it altogether — it is a matter of implementation quality how garbage collection is implemented, as long as no objects are collected that are still reachable.

object.__init__(self[, ...])

Called after the instance has been created (by new()), but before it is returned to the caller. [...]

object.__del__(self)

Called when the instance is about to be destroyed. [...]

So the object instance already exists when __init__ is called, as it is created by __new__. But for Python in general, there is no guarantee that __del__ will ever be called.

The following only applies to CPython, the reference implementation of Python.

Note (for object.__del__(self))

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. [...]

Here __del__ is called whenever the reference count for the instance drops to 0. This has nothing to do with garbage collection. A little experiment:

>>> class A:
...   def __del__(self): print "del"
... 
>>> a = A()
>>> a = None
del
>>> import gc
>>> gc.disable() 
>>> a = A()
>>> a = None
del

As you can see, the destructor is called even when GC is explicitly disabled.

Note that this also implies that if you have cycles in your object hierarchy, you end up with objects for which __del__ never gets called, as the Python GC can't deal with reference cycles.

>>> a1 = A()
>>> a2 = A()
>>> a1.x = a2
>>> a2.x = a1
>>> a1 = None
>>> a2 = None
>>> import gc
>>> gc.collect()
4
>>> gc.garbage
[<__main__.A instance at 0x7f2c66a1d7e8>, <__main__.A instance at 0x7f2c66a1d830>]
相关阅读:
Top