Mastering Objectoriented Python
上QQ阅读APP看书,第一时间看更新

The reference count and destruction

For the CPython implementation, objects have a reference count. The count is incremented when the object is assigned to a variable and decremented when the variable is removed. When the reference count is zero, the object is no longer needed and can be destroyed. For simple objects, __del__() will be invoked and the object will be removed.

For complex objects that have circular references among objects, the reference count might never go to zero and __del__() can't be invoked easily.

The following is a class that we can use to see what happens:

class Noisy:
    def __del__( self ):
        print( "Removing {0}".format(id(self)) )

We can create (and see the removal of) these objects as follows:

>>> x= Noisy()
>>> del x
Removing 4313946640

We created and removed a Noisy object, and almost immediately we saw the message from the __del__() method. This indicates that the reference count properly went to zero when the x variable was deleted. Once the variable is gone, there's no longer a reference to the instance of Noisy and it, too, can be cleaned up.

The following is a common situation that involves the shallow copies that are often created:

>>> ln = [ Noisy(), Noisy() ]
>>> ln2= ln[:]
>>> del ln

There's no response to this del statement. The Noisy objects have not had their reference counts go to zero yet; they're still being referenced somewhere, as shown in the following code snippet:

>>> del ln2
Removing 4313920336
Removing 4313920208

The ln2 variable was a shallow copy of the ln list. The Noisy objects were referenced in two lists. They could not be destroyed until both lists were removed, reducing the reference counts to zero.

There are numerous other ways to create shallow copies. The following are a few ways to create shallow copies of objects:

a = b = Noisy()
c = [ Noisy() ] * 2

The point here is that we can often be confused by the number of references to an object that can exist because shallow copies are prevalent in Python.