__new__ ,__init__和__del__

本文深入探讨了Python中的魔术方法__new__、__init__和__del__,解释了它们的作用和使用场景,并提供了实例代码。此外,文章还介绍了如何利用__new__方法实现单例模式。

  每个人都知道一个最基本的魔术方法, __init__ 。通过此方法我们可以定义一个对象的初始操作。然而,当我调用 x =SomeClass() 的时候, __init__ 并不是第一个被调用的方法。实际上,还有一个叫做 __new__ 的方法,来构造这个实例。然后给在开始创建时候的初始化函数来传递参数。在对象生命周期的另一端,也有一个 __del__ 方法。我们现在来近距离的看一看这三个方法:

__new__(cls, [...) __new__ 是在一个对象实例化的时候所调用的第一个方法。它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法。 __new__ 方法相当不常用,但是它有自己的特性,特别是当继承一个不可变的类型比如一个tuple或者string。我不希望在 __new__ 上有太多细节,因为并不是很有用处,但是在 Python文档 中有详细的阐述。


__init__(self, […) 此方法为类的初始化方法。当构造函数被调用的时候的任何参数都将会传给它。(比如如果我们调用x = SomeClass(10, 'foo')),那么 __init__ 将会得到两个参数10和foo。 __init__ 在Python的类定义中被广泛用到。


__del__(self) 如果 __new__ 和 __init__ 是对象的构造器的话,那么 __del__ 就是析构器。它不实现语句 del x (以上代码将不会翻译为 x.__del__() )。它定义的是当一个对象进行垃圾回收时候的行为。当一个对象在删除的时需要更多的清洁工作的时候此方法会很有用,比如套接字对象或者是文件对象。注意,如果解释器退出的时候对象还存存在,就不能保证 __del__ 能够被执行,所以 __del__ can’t serve as a replacement for good coding practices ()~~~~~~~

放在一起的话,这里是一个 __init__ 和 __del__ 实际使用的例子。

from os.path import join

class FileObject:
    '''给文件对象进行包装从而确认在删除时文件流关闭'''

    def __init__(self, filepath='~', filename='sample.txt'):
        #读写模式打开一个文件
        self.file = open(join(filepath, filename), 'r+')

    def __del__(self):
        self.file.close()
        del self.file


继承自object的新式类才有__new__

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

例:

>>> class E(object):
	def __init__(self):
		print "init"
	def __new__(cls,*args,**kwargs):
		print "new %s"%cls
		return super(E, cls).__new__(cls, *args,**kwargs)

	
>>> te = E()
new <class '__main__.E'>
init
>>> 
>>> print type(te)
<class '__main__.E'>
或者

>>> class D(object):
	def __init__(self):
		print "init"
	def __new__(cls,*args,**kwargs):
		print "new %s"%cls
		return object.__new__(D,*args,**kwargs)

	
>>> td = D()
new <class '__main__.D'>
init
>>> print type(td)
<class '__main__.D'>
若__new__没有正确返回 当前类cls 的实例,那__init__是不会被调用的,即使是父类的实例也不行

>>> class B(object):
	def __init__(self):
		print "init"

		
>>> class C(object):
	def __init__(self):
		print "init"
	def __new__(cls,*args,**kwargs):
		print "new %s"%cls
		return object.__new__(B,*args,**kwargs)

	
>>> tc = C()
new <class '__main__.C'>
>>> print type(tc)
<class '__main__.B'>
若没有继承object,也会自动创建对象,但不会执行本身的__new__方法,至于是否调用了object的__new__方法有待探究

>>> class G():
	def __init__(self):
		print "init"
	def __new__(cls,*args,**kwargs):
		print "new %s"%cls
		return object.__new__(G,*args,**kwargs)

	
>>> tg = G()
init
>>> print type(tg)
<type 'instance'>
>>> isinstance(tg,G)
True

__new__ 的作用

依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
首先我们来看一下第一个功能,具体我们可以用int来作为一个例子:
假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。

class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))

i = PositiveInteger(-3)
print i

但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。
这是修改后的代码:

class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))

i = PositiveInteger(-3)
print i

通过重载__new__方法,我们实现了需要的功能。
另外一个作用,关于自定义metaclass。其实我最早接触__new__的时候,就是因为需要自定义 metaclass,但鉴于篇幅原因,我们下次再来讲python中的metaclass和__new__的关系。



用__new__来实现单例

事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton) 。
因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。

class Singleton(object):
    def __new__(cls):
        # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

obj1 = Singleton()
obj2 = Singleton()

obj1.attr1 = 'value1'print obj1.attr1, obj2.attr1
print obj1 is obj2

输出结果:

value1 value1
True


可以看到obj1和obj2是同一个实例。







代码转载自:https://pan.quark.cn/s/9cde95ebe57a 横道图,亦称为甘特图,是一种可视化的项目管理手段,用于呈现项目的进度安排时间框架。 在信息技术领域,特别是在项目执行与软件开发范畴内,横道图被普遍采用来监控作业、配置资源以及保障项目能按时交付。 此类图表借助水平条带图示来标示各个任务的起止时间点,使项目成员与管理者可以明确掌握项目的整体发展状况。 周期表或可指代计算机科学中的“作业调度周期表”或“资源配置周期表”。 在计算机系统中,作业调度是一项核心功能,它规定了哪个进程或线程能够在中央处理器上执行以及执行的具体时长。 周期表有助于系统管理者洞察作业的执行频率资源使用状况,进而提升系统的运作效能响应能力。 不仅如此,周期表也可能意指数据处理或研究中的周期性文档,如在金融分析中按期更新的市场信息文档。 在压缩文件“横道图,周期表.zip”内含的“横道图,周期表.doc”文件,很可能是对某个项目或任务管理的详尽阐述,涵盖利用横道图来制定展示项目的时间进程,以及可能牵涉的周期性作业调度或资源配置情形。 文件或许包含以下部分:1. **项目简介**:阐述项目的目标、范畴、预期成效及参与项目的团队成员。 2. **横道图详述**:具体列出了项目中的各项任务,每个任务的启动与终止时间,以及它们之间的关联性。 横道图通常涵盖关键节点,这些节点是项目中的重要事件,象征重要阶段的实现。 3. **任务配置**:明确了每个任务的责任归属,使项目成员明晰自己的职责截止日期。 4. **进展更新**:若文件是动态维护的,可能会记录项目的实际进展与计划进展的对比,有助于识别延误并调整计划。 5. **周期表探讨**:深入说明了周期性作业的调度,如定期的会议、报告递交、...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值