Python-__new__ 和 __init__ 的区别
·
分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程
https://www.captainai.net/troubleshooter
这两个方法是 Python 类中的特殊方法,用于控制对象的创建和初始化,但它们的作用和执行时机完全不同。
一、核心区别
| 特性 | __new__ | __init__ |
|---|---|---|
| 作用 | 创建实例对象 | 初始化实例对象 |
| 调用时机 | 在 __init__ 之前 | 在 __new__ 之后 |
| 第一个参数 | cls(类本身) | self(实例对象) |
| 返回值 | 必须返回实例对象 | 不返回(返回 None) |
| 是否必须 | 可选,一般不需要重写 | 可选,常用 |
| 使用场景 | 控制实例创建过程 | 设置实例属性 |
二、执行顺序
class MyClass:
def __new__(cls, *args, **kwargs):
print("1. __new__ 被调用")
instance = super().__new__(cls)
print(f" 创建实例: {instance}")
return instance
def __init__(self, value):
print("2. __init__ 被调用")
self.value = value
print(f" 初始化实例: {self}")
obj = MyClass(10)
print(f"最终对象: {obj}")
输出:
1. __new__ 被调用
创建实例: <__main__.MyClass object at 0x...>
2. __init__ 被调用
初始化实例: <__main__.MyClass object at 0x...>
最终对象: <__main__.MyClass object at 0x...>
三、详细说明
__new__ 方法
-
类方法(虽然不用
@classmethod装饰) -
负责分配内存,创建实例对象
-
必须返回一个实例对象(通常是
cls的实例) -
如果
__new__返回的不是当前类的实例,__init__不会被调用
__init__ 方法
-
实例方法
-
负责初始化已创建的实例
-
设置实例属性
-
不应该返回任何值(返回
None)
四、典型使用场景
1. 单例模式
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
print("创建单例实例")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value):
print("初始化单例")
self.value = value
# 测试
s1 = Singleton(10)
s2 = Singleton(20)
print(s1 is s2) # True(同一个对象)
print(s1.value) # 20(最后初始化的值)
输出:
创建单例实例
初始化单例
初始化单例
True
20
2. 不可变类(如继承 int、str)
class PositiveInteger(int):
def __new__(cls, value):
# 在创建之前进行验证
if value <= 0:
raise ValueError("必须是正整数")
# 创建整数对象
return super().__new__(cls, value)
def __init__(self, value):
# int 是不可变类型,__init__ 中无法修改值
print(f"创建正整数: {value}")
try:
n1 = PositiveInteger(5) # 正常
n2 = PositiveInteger(-3) # 抛出异常
except ValueError as e:
print(e) # 必须是正整数
3. 缓存对象
class CachedObject:
_cache = {}
def __new__(cls, key, value):
# 如果对象已存在,直接返回缓存的对象
if key in cls._cache:
print(f"从缓存返回对象: {key}")
return cls._cache[key]
# 创建新对象
print(f"创建新对象: {key}")
instance = super().__new__(cls)
cls._cache[key] = instance
return instance
def __init__(self, key, value):
# 避免重复初始化
if hasattr(self, '_initialized'):
return
print(f"初始化对象: {key}")
self.key = key
self.value = value
self._initialized = True
# 测试
obj1 = CachedObject("a", 1)
obj2 = CachedObject("a", 2) # 从缓存返回,不会重新初始化
print(obj1 is obj2) # True
print(obj2.value) # 1(保留第一次初始化的值)
输出:
创建新对象: a
初始化对象: a
从缓存返回对象: a
True
1
4. 子类化不可变类型
class SliceRange(tuple):
"""自定义范围类,基于 tuple"""
def __new__(cls, start, end, step=1):
# 创建元组
if step > 0:
values = range(start, end, step)
else:
values = range(start, end, step)
return super().__new__(cls, values)
def __init__(self, start, end, step=1):
# 存储参数供方法使用
self.start = start
self.end = end
self.step = step
sr = SliceRange(1, 10, 2)
print(sr) # (1, 3, 5, 7, 9)
print(sr.start) # 1
print(len(sr)) # 5
更多推荐



所有评论(0)