__new__()
是一种负责创建类实例的静态方法,它无需使用 @staticmethod
装饰器修饰,且该方法会优先 __init__()
初始化方法被调用。
一般情况下,覆写 __new__()
的实现将会使用合适的参数调用其超类的 super().__new__()
,并在返回之前修改实例。例如:
13_newMethodInCls.py
class DemoClass:
instances_created = 0
def __new__(cls, *args, **kwargs):
print("__new__():", cls, args, kwargs)
instance = super().__new__(cls)
print('instance:', instance)
instance.number = cls.instances_created
cls.instances_created += 1
return instance
def __init__(self, attribute):
print("__init__():", self, attribute)
self.attribute = attribute
test1 = DemoClass("abc")
print('test1:', test1)
print("\n----------------\n")
test2 = DemoClass("xyz")
print('test2:', test2)
print("\n----------------\n")
print(test1.number, test1.instances_created)
print(test2.number, test2.instances_created)
输出结果为:
__new__(): <class '__main__.DemoClass'> ('abc',) {}
instance: <__main__.DemoClass object at 0x00000161CA9F2EB0> 0
__init__(): <__main__.DemoClass object at 0x00000161CA9F2EB0> abc
test1: <__main__.DemoClass object at 0x00000161CA9F2EB0>
----------------
__new__(): <class '__main__.DemoClass'> ('xyz',) {}
instance: <__main__.DemoClass object at 0x00000161CA9F2DF0> 1
__init__(): <__main__.DemoClass object at 0x00000161CA9F2DF0> xyz
test2: <__main__.DemoClass object at 0x00000161CA9F2DF0>
----------------
0 2
1 2
Python中存在于类中的构造方法
__init__()
负责将类实例化,而在__init__()
执行之前,__new__()
负责制造这样的一个实例对象,以便__init__()
去让该实例对象更加的丰富(为其添加属性等)。同时:
__new__()
方法还决定是否要使用该__init__()
方法,因为__new__()
可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。
如果将类比喻为工厂,那么init()方法则是该工厂的生产工人,init()方法接受的初始化参 数则是生产所需原料,init()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 new()则是生产部经理,new()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。
需要注意的是
- 在实例化
test1
的时候,“项目经理”把自己的cls.instances_created
和test1.instances_created
地址弄成一样的了 - 在在实例化
test2
的时候,“项目经理”还是那个项目经理,把自己的cls.instances_created
地址改变赋给test2.instances_created
,此时test1.instances_created
地址跟着改变。
所以最后test1
、test2
的instances_created
属性值一样。
用这个原理,就可以将__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