一、两者的关系
python中的构造函数是__ new __ 方法,__ init __ 只是初始化方法,也就是说在调用__ init __ 之前,我们的实例就已经被创建好了,__ init __只是为这个实例赋上了一些值。
#__init__的用法
class Student:
def __init__(self,name,gender):
self.name = name
self.gender = gender
#__new__的用法
def __new__(cls,*args,**kwargs):
return super().__new__(cls,*args,**kwargs)
从代码可以看到,__ new __ 函数基本什么也没做,就原封不动地调用了父类的构造函数,这里隐藏着类的创建逻辑,是根据继承关系一级一级创建的。根据逻辑我们可以知道,当我们创建一个实例的时候,实际是先调用的__ new __ 函数创建实例,然后再调用__ init __ 对实例进行的初始化。
二、__ new __函数的应用场景
1、单例模式
#不管创建多少次,仅仅只有一个对象,这样的模式叫做单例,创建的多个对象都指向同一个内存空间
class SingletonObject:
def __new__(cls,*args,**kwagrs):
if not hasattr(SingletonObject,"_instance"):
SingletonObject._instance = object.__new__(cls)
return SingletonObject._instance
def __init__(self):
pass
2、控制实例的创建
因为实例的创建是先调用__ new __ 再调用 __ init __,所以当调用 __ new __的时候返回None,那么最后得到的结果也是None,通过这个特性,我们可以控制类的创建
#比如我们想要创建一个类,它是一个int,但是不能为0值,我们就可以利用__new__的这个特性来实现:
class NonZero(int):
def __new__(cls,value):
return super().__new__(cls,value) if value != 0 else None
#那么当我们用0值来创建它的时候就会得到一个None,而不是一个实例。
3、工厂模式
所谓的工厂模式是指通过一个接口,根据参数的取值来创建不同的实例。创建过程的逻辑对外封闭,用户不必关系实现的逻辑。就好比一个工厂可以生产多种零件,用户并不关心生产的过程,只需要告知需要零件的种类。也因此称为工厂模式。
class Lastofus:
def play(self):
print("this Last Of Us is really funny")
class Uncharted:
def play(self):
print("the Uncharted is really funny")
class PsGame:
def play(self):
print("PS has many games")
class GameFactory:
games = {"last_of_us": LastOfUs, "uncharted": Uncharted}
def __new__(cls,name):
if name in cls.game:
return cls.games[name]()
return PsGame()
uncharted = GameFactory("uncharted")
last_of_us = GameFactory("last_of_us")
uncharted.play()
last_of_us.play()
"""
the Uncharted is really funny
this Last Of Us is really funny
"""