So when does it gets decremented? When the variable gets out of scope, or voluntarily when you call 'del', just as in C++ or D. The difference lies in the notion of scope which is just different than of the one of C/C++/D/Java/C#.
Example:
from __future__ import print_function
class Foo:
def __init__(self, text):
self.text = text
def __del__(self):
print("deleting %s" % self)
def __str__(self):
return ("%r(%s)" % (self,self.text))
def bar():
if True:
print("+scope 1 in bar")
f = Foo("in bar")
print("-scope 1 in bar")
if True:
print("+scope 1")
bar()
print("bar quit")
if True:
print("+scope 2")
f = Foo("global")
print("-scope 2")
print(f)
print("-scope 1")
will output: +scope 1
+scope 1 in bar
-scope 1 in bar
deleting <__main__.Foo instance at 0x1004d4a70>(in bar)
bar quit
+scope 2
-scope 2
<__main__.Foo instance at 0x1004d4a70>(global)
-scope 1
deleting <__main__.Foo instance at 0x1004d4a70>(global)
By now you have noticed that the scope is function-wide (or module-wide for global code).So you can write the exact same code that he wrote in C++ in python and it would work the exact same way, and it doesn't create the Java dispose() mess of slide 12.
There is a twist though. Exceptions. Say you have an uncaught exception raised in bar(), then the Foo object created in bar() will be referenced in the stack frame of the exception, which belongs to the caller of bar(), so the Foo object reference count will drop to zero only after the caller scope closes.
Try it for yourself by adding this function:
def baz():¬
try:¬
bar()¬
except:¬
print("caught")¬
and calling it in place of bar() after "+scope 1", while raising any exception in bar().If you want to override this behavior you can just as well call del when you want to get rid of the object, which is just as forgettable as adding 'scope' to variables declarations in the author's almighty D.
An interesting task is to examine (and why not, control) the gc behavior with the gc module (http://docs.python.org/library/gc.html)
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.
CPython implementation detail: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references. See the documentation of the gc module for information on controlling the collection of cyclic garbage. Other implementations act differently and CPython may change. Do not depend on immediate finalization of objects when they become unreachable (ex: always close files).
As the Zen of Python says: explicit is better than implicit and in the face of ambiguity, refuse the temptation to guess. Hence the decision Python (IMHO rightfully) made about being explicit about it, and allow whatever current of future memory management scheme to be appropriate and forward compatible. This is already happening with PyPy (http://pypy.org/compat.html).