Python __new__方法
__new__是对象创建的第一步,负责分配内存并返回实例,__init__随后初始化实例。
new 与 init 区别
Python
class Demo:
def __new__(cls, *args, **kwargs):
print("1. __new__: 创建对象")
instance = super().__new__(cls)
return instance
def __init__(self, *args, **kwargs):
print("2. __init__: 初始化对象")
self.value = args[0] if args else None
obj = Demo("test")
# 输出顺序:
# 1. __new__: 创建对象
# 2. __init__: 初始化对象
| 方法 | 职责 | 参数 | 返回值 |
|---|---|---|---|
__new__ | 创建对象 | cls + 参数 | 实例对象 |
__init__ | 初始化对象 | self + 参数 | None |
Python
# __new__ 可以决定是否调用 __init__
class SkipInit:
def __new__(cls, *args, **kwargs):
print("__new__ called")
# 返回其他类或 None 会跳过 __init__
return None
def __init__(self):
print("__init__ called") # 不会执行
obj = SkipInit()
print(obj) # None
单例模式实现
Python
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value):
# 注意:每次调用都会执行 __init__
self.value = value
s1 = Singleton(1)
s2 = Singleton(2)
print(s1 is s2) # True(同一实例)
print(s1.value) # 2(被第二次 __init__ 覆盖)
Python
# 完善的单例:避免重复 __init__
class ProperSingleton:
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value):
if not self._initialized:
self.value = value
self._initialized = True
s1 = ProperSingleton(1)
s2 = ProperSingleton(2)
print(s1.value) # 1(未被覆盖)
print(s1 is s2) # True
Python
# 多例模式(有限实例)
class Multiton:
_instances = {}
def __new__(cls, key):
if key not in cls._instances:
cls._instances[key] = super().__new__(cls)
return cls._instances[key]
a1 = Multiton('A')
a2 = Multiton('A')
b1 = Multiton('B')
print(a1 is a2) # True
print(a1 is b1) # False
控制实例类型
Python
# 根据参数返回不同子类
class Shape:
def __new__(cls, sides, **kwargs):
if sides == 3:
return Triangle(**kwargs)
elif sides == 4:
return Rectangle(**kwargs)
elif sides == 5:
return Pentagon(**kwargs)
else:
return super().__new__(cls)
class Triangle(Shape):
def __init__(self, **kwargs):
self.sides = 3
self.name = "triangle"
class Rectangle(Shape):
def __init__(self, **kwargs):
self.sides = 4
self.name = "rectangle"
class Pentagon(Shape):
def __init__(self, **kwargs):
self.sides = 5
self.name = "pentagon"
tri = Shape(3)
rect = Shape(4)
print(type(tri).__name__) # Triangle
print(type(rect).__name__) # Rectangle
不可变对象实现
Python
# 模拟 tuple 的不可变性
class ImmutablePoint:
__slots__ = ('_x', '_y')
def __new__(cls, x, y):
instance = super().__new__(cls)
instance._x = x
instance._y = y
return instance
def __init__(self, x, y):
# __init__ 不设置值,避免重复初始化问题
pass
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __setattr__(self, name, value):
raise AttributeError("不可变对象")
p = ImmutablePoint(1, 2)
print(p.x, p.y) # 1 2
# p.x = 10 # AttributeError
继承不可变类型
Python
# 继承 tuple
class NamedTuple(tuple):
"带名称的元组"
__slots__ = () # 避免创建 __dict__
def __new__(cls, name, values):
# tuple.__new__ 接受可迭代对象
instance = super().__new__(cls, values)
instance._name = name # 通过 __new__ 添加属性
return instance
@property
def name(self):
return self._name
nt = NamedTuple("coordinates", (1, 2, 3))
print(nt.name) # coordinates
print(nt[0]) # 1
Python
# 继承 int
class PositiveInt(int):
"正整数类型"
def __new__(cls, value):
if value < 0:
raise ValueError("必须是正整数")
return super().__new__(cls, value)
def __repr__(self):
return f"PositiveInt({self})"
n = PositiveInt(10)
print(n + 5) # 15(继承 int 的运算)
print(type(n)) # PositiveInt
# PositiveInt(-1) # ValueError
缓存实例
Python
class CachedInstance:
"缓存已创建的实例"
_cache = {}
_cache_limit = 100
def __new__(cls, key):
# 检查缓存
if key in cls._cache:
return cls._cache[key]
# 创建新实例
instance = super().__new__(cls)
# 缓存管理
if len(cls._cache) >= cls._cache_limit:
cls._cache.clear()
cls._cache[key] = instance
return instance
def __init__(self, key):
self.key = key
a1 = CachedInstance('a')
a2 = CachedInstance('a')
b = CachedInstance('b')
print(a1 is a2) # True(缓存命中)
print(a1 is b) # False
new 与描述符
Python
class Descriptor:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, owner):
if obj is None:
return self
return getattr(obj, f'_internal_{self.name}', None)
def __set__(self, obj, value):
setattr(obj, f'_internal_{self.name}', value)
class Controlled:
attr = Descriptor()
def __new__(cls, *args, **kwargs):
instance = super().__new__(cls)
# __new__ 中可以设置描述符控制的属性
setattr(instance, '_internal_attr', kwargs.get('attr', 0))
return instance
def __init__(self, **kwargs):
# __init__ 中通过描述符设置
if 'attr' in kwargs:
self.attr = kwargs['attr']
obj = Controlled(attr=10)
print(obj.attr) # 10
跳过 init 的场景
Python
class DatabaseConnection:
"数据库连接:__new__ 完成核心初始化"
def __new__(cls, url):
instance = super().__new__(cls)
# 连接数据库
instance._url = url
instance._connected = True
return instance
def __init__(self, url):
# __init__ 可能被多次调用,避免重复初始化
if not hasattr(self, '_setup_done'):
self._setup_done = True
# 其他配置
conn = DatabaseConnection("postgres://...")
# __new__ 已完成连接,__init__ 仅做额外配置
要点总结
- **
__new__创建对象,__init__**初始化对象 __new__返回其他对象或None会跳过__init__- 单例模式通过
__new__控制实例数量 - 继承不可变类型(tuple、int)必须用
__new__设置值 __new__可实现实例缓存、类型选择等高级控制
📝 发现内容有误?点击此处直接编辑