面试题答案
一键面试区别
- 调用时机:
__new__
是在实例创建之前被调用,它的任务是创建并返回一个实例对象。__init__
是在实例创建之后被调用,用于对新创建的实例进行初始化操作。
- 参数:
__new__
第一个参数是类本身(通常命名为cls
),后续参数是传递给类构造函数的参数。__init__
第一个参数是实例对象本身(通常命名为self
),后续参数同样是传递给类构造函数的参数。
- 返回值:
__new__
必须返回一个实例对象(通常是通过调用super().__new__(cls)
得到),如果不返回实例对象,__init__
不会被调用。__init__
不需要返回值(实际上默认返回None
)。
联系
__new__
创建实例对象后,会将该对象作为self
参数传递给__init__
方法,以便进行初始化操作。
重写__new__
方法的场景举例
- 实现单例模式:
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
pass
a = Singleton()
b = Singleton()
print(a is b)
在这个例子中,通过重写__new__
方法,确保无论创建多少次实例,都返回同一个实例对象,实现了单例模式。因为__new__
方法只在第一次创建实例时真正创建对象,后续创建时直接返回已有的实例。
2. 创建不可变实例:
class ImmutableClass:
def __new__(cls, value):
instance = super().__new__(cls)
instance.value = value
return instance
def __init__(self, value):
pass
def __setattr__(self, name, value):
raise AttributeError("This instance is immutable")
obj = ImmutableClass(10)
try:
obj.value = 20
except AttributeError as e:
print(e)
这里重写__new__
方法在创建实例时就设置好属性值,同时通过重写__setattr__
方法禁止对实例属性的修改,达到实例不可变的目的。