先看如下代码:
class User:
def __new__(cls):
print("new")
a = super().__new__(cls)
print(a)
print(cls.__bases__)
return a
def __init__(self):
print("init")
print(self)
a = User()
输出:
new
<__main__.User object at 0x0000000003E072B0>
(<class 'object'>,)
init
<__main__.User object at 0x0000000003E072B0>
说明在定义一个对象时, __new__在__init__之前被调用,且__new__返回的cls即为__init__的self,__init__不需要返回值
返回super().__new__(cls)(或者object.__new__(cls))的作用是什么呢?User的父类是object,User调用父类的__new__是为了继承父类的方法和属性,什么情况下使用 __new__() 呢?答案很简单,在 __init__() 不够用的时候。
比如,在定义元类的时候,
比如,在需要对属性的名称进行规范化的时候(属性名可以作为__new__函数的参数进行操作),
比如,要修改固定类的属性时(比如,修改int总为正整数,str总为大写,定义单例模式)等等。
1、__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
2、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用,即使是父类的实例也不行。
__init__用法:
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Ahahahah')
else:
print('No thanks!')
class SongBird(Bird):
def __init__(self):
self.sound = 'Squawk'
super(SongBird,self).__init__()
#super().__new__(self)
def sing(self):
print("self.sing()")
sb = SongBird()
sb.sing() # 能正常输出
sb.eat()
输出:
self.sing()
Ahahahah
当子类定义了__init__函数时,必须显式的执行super(子类名,self).__init__()(或者super().__init__()),用来继承父类的属性,否则父类属性将不会被继承
__new__应用于单例模式
什么是单例模式,顾名思义,系统中只能存在一个类的一个实例,所有对实例的属性的操作都是全局的。看代码:
class A:
__isinstance = False # 设置一个私有变量,默认没有被实例化
def __init__(self, name):
self.name = name #name属性
def __new__(cls, *args, **kwargs):
if cls.__isinstance:
return cls.__isinstance # 返回实例化对象
cls.__isinstance = object.__new__(cls) # 否则实例化
return cls.__isinstance # 返回实例化的对象
# 实例化三个对象
a = A('张三')
b = A('李四')
c = A('王五')
# 打印三个对象的地址,结果都是一个地址
print(a)
print(b)
print(c)
print(a.name)
print(b.name)
print(c.name)
a.name='xxxx'
print(c.name)
输出
<__main__.A object at 0x0000000002354978>
<__main__.A object at 0x0000000002354978>
<__main__.A object at 0x0000000002354978>
王五
王五
王五
xxxx