This is dynamic language. `Person` is NOT a C++ or java like `class`. `
Person` is just a name in global scope referring to an instance of `type`.
In another word `Person` is nothing but a key in the global name dictionary.
During interpretor exiting, as @hatemaths pointing out, when __del__ get
called, there is no guarantee any referred global name still exists (
deleting order is unpredictable). In this case `Person` in the global scope
has already being destroyed. But in the local scope it still exist. That is
why if u use the reference in local scope: `cls` in @classmethod, it will
still work.
Here I will show some detail with examples:
try to modify my class as following:
@classmethod
def __poppopulation__(cls):
print "gloals: ", globals()
print "locals: ", locals()
cls.population -= 1
if cls.population == 0:
print 'I am the last one, now I am gone'
else:
print 'There are still %d people left;' % cls.population
Then modify the instantiation part:
Ao = Person('Ao Liu');
Ao.howMany();
John = Person('John Bay');
John.howMany();
Chris = Person('Chris Tunnel');
Chris.howMany();
David = Person('David');
David.howMany();
print globals()
what u will see is like this:
#############################
The person'sname is Ao Liu
I am the last one, but I am still here
The person'sname is John Bay
We have 2 people here.
The person'sname is Chris Tunnel
We have 3 people here.
The person'sname is David
We have 4 people here.
#############################
#Here is the global dict:
globals(): {'__builtins__': , '__file_
_': './delproblem2b.py', 'Ao': <__main__.person at="" object="">, '
__package__': None, 'sys': , 'Person': main__.Person'>, 'Chris': <__main__.person at="" object="">, '__
name__': '__main__', 'John': <__main__.person at="" object="">, 'os
': , '__doc__': None, 'David':
<__main__.person at="" object="">}
#############################
# so after Ao get del, still 'Person':
###
Ao Liu says bye;
gloals: {'__builtins__': , 'Ao': None,
'__package__': None, 'sys': , 'Person': main__.Person'>, 'Chris': <__main__.person at="" object="">, '__
name__': '__main__', 'John': <__main__.person at="" object="">, 'os
': , '__doc__': None, 'David':
<__main__.person at="" object="">}
locals: {'cls': }
There are still 3 people left;
#############################
# But when Chris get del, 'Person': None
###
Chris Tunnel says bye;
gloals: {'__builtins__': , 'Ao': None,
'__package__': None, 'sys': None, 'Person': None, 'Chris': None, '__name__'
module 'os' from '/usr/lib/python2.7/os.pyc'>, '__doc__': None, 'David': <__>main__.Person object at 0x7ff088126dd0>}
locals: {'cls': }
There are still 2 people left;
#############################
# because 'Person' is refer to None, Person.population is actually,
#None.population. This is why u get an error in ur code.
###
John Bay says bye;
gloals: {'__builtins__': , 'Ao': None,
'__package__': None, 'sys': None, 'Person': None, 'Chris': None, '__name__'
'__doc__': None, 'David': <__main__.person at="" object="">}
##But in the local scope of the instance of `Person class` is still ##exist.
locals: {'cls': }
There are still 1 people left;
David says bye;
gloals: {'__builtins__': , 'Ao': None,
'__package__': None, 'sys': None, 'Person': None, 'Chris': None, '__name__'
locals: {'cls': }
I am the last one, now I am gone
let's continue to play with the global name and demonstrate what the `
unpredictable` means. Create a new script with the *OP's* post as myscript1a.
py, with following modification:
add A to all the instances:
Ao = Person('Ao Liu');
Ao.howMany();
AJohn = Person('John Bay');
AJohn.howMany();
AChris = Person('Chris Tunnel');
AChris.howMany();
ADavid = Person('David');
ADavid.howMany();
###################
Chris Tunnel says bye;
There are still 3 people left;
David says bye;
There are still 2 people left;
Ao Liu says bye;
There are still 1 people left;
John Bay says bye;
Exception AttributeError: "'NoneType' object has no attribute '
population'" in 0x7f2f1f2e9ea8>> ignored
##we can see here the behavior changed!
So the behavior is not stable, it might related to the variable name, or to
other stuff, not for sure.
In certain cases, this will even create memory leak.
In general, as @libralibra said, we should avoid to use method __del__ with
global reference either explicitly or implicitly
I hope this will clear all the doubts u have. As I said, you should keep in
mind, Python is a dynamic language, which is nothing like the Java/C++, most
of the concepts you have learned in Java and C++ will surprise u in Python.