构造函数和析构函数是如何工作的?
我正在试着理解这段代码:
class Person:
'''Represents a person '''
population = 0
def __init__(self,name):
//some statements and population += 1
def __del__(self):
//some statements and population -= 1
def sayHi(self):
'''grettings from person'''
print 'Hi My name is %s' % self.name
def howMany(self):
'''Prints the current population'''
if Person.population == 1:
print 'i am the only one here'
else:
print 'There are still %d guyz left ' % Person.population
rohan = Person('Rohan')
rohan.sayHi()
rohan.howMany()
sanju = Person('Sanjivi')
sanju.howMany()
del rohan # am i doing this correctly?
这个析构函数是怎么被调用的?是自动调用的,还是我需要在“主”程序/类中像上面那样添加什么东西?
输出结果:
正在初始化个人数据
******************************************
正在初始化罗汉
******************************************
现在的人口是:1
嗨,我叫罗汉
我是这里唯一的人
正在初始化个人数据
******************************************
正在初始化桑吉维
******************************************
现在的人口是:2
如果有人去世:
******************************************
桑吉维再见,世界
现在还有1个人
我是这里唯一的人
如果有人去世:
******************************************
罗汉再见,世界
我是地球上最后一个人
现在的人口是:0
如果需要的话,我可以把整个课程的内容也贴上来。我正在学习的内容来自: http://www.ibiblio.org/swaroopch/byteofpython/read/
2 个回答
根据我早期的CPTS经验,以下是我的理解:
构造函数:构造函数主要用于类中,用来初始化类的值,并且在创建对象时可以做一些后台工作。如果你在创建对象的时候传入了一些值,这里就是把这些值分配给类里面的变量的地方。(在这个例子中,创建对象时你会增加一个变量,这个变量用来记录人口数量)。
析构函数:析构函数用来清理类。在Python中,由于有垃圾回收机制,这个功能没有像C++那样重要,因为C++可能会留下悬挂指针。(在这个例子中,当对象被销毁时,你会减少人口数量的变量)。
这里有一个稍微带点个人观点的回答。
不要使用 __del__
。这不是 C++ 或者其他专门为析构函数设计的语言。其实在 Python 3.x 中,__del__
方法应该被淘汰,尽管我相信总会有人找到合适的使用场景。如果你真的需要使用 __del__
,那么要注意以下基本限制,详细信息可以查看 这篇文档:
__del__
是在垃圾回收器收集对象时被调用的,而不是在你失去对某个对象的最后引用时,也不是在你执行del object
时。__del__
需要负责调用父类中的__del__
,不过这是否按照方法解析顺序(MRO)来调用,还是仅仅调用每个父类,这点并不明确。- 如果有
__del__
,那么垃圾回收器就会放弃检测和清理任何循环引用,比如失去对链表的最后引用。你可以通过gc.garbage
获取被忽略的对象列表。有时候可以使用弱引用来避免循环引用。这点时不时会被讨论:可以查看 这篇讨论。 __del__
函数可以“作弊”,保存对某个对象的引用,从而阻止垃圾回收。- 在
__del__
中显式抛出的异常会被忽略。 __del__
更像是__new__
的补充,而不是__init__
。这点可能会让人感到困惑。可以查看 这篇文章来了解更多和一些注意事项。__del__
在 Python 中并不是一个“受欢迎”的特性。你会发现 sys.exit() 的文档没有说明在退出之前是否会进行垃圾回收,而且会有很多奇怪的问题。调用全局变量的__del__
会导致奇怪的顺序问题,比如 这个问题。如果__init__
失败,__del__
是否应该被调用?可以查看 这条长讨论。
但是,另一方面:
__del__
可以确保你不会忘记调用关闭语句。可以查看 这篇文章,它提供了支持__del__
的观点。这通常是关于释放 ctypes 或其他特殊资源。
还有我个人不喜欢 __del__
函数的原因。
- 每次有人提到
__del__
,讨论就会变得混乱,信息量激增。 - 它违反了 Python 的一些原则:
- 复杂的东西比复杂的东西更好。
- 特殊情况并不足以打破规则。
- 错误不应该悄无声息地过去。
- 面对模糊的情况,拒绝猜测的诱惑。
- 应该有一种——最好只有一种——明显的做法。
- 如果实现难以解释,那就是个坏主意。
所以,找个理由不要使用 __del__
。