
本文详解 Python 中重写 __new__ 时如何安全接收并传递参数:__new__ 只需将 cls 传给 super().__new__(cls),其余参数由 Python 自动转发至 __init__,无需手动传递。
本文详解 python 中重写 `__new__` 时如何安全接收并传递参数:`__new__` 只需将 `cls` 传给 `super().__new__(cls)`,其余参数由 python 自动转发至 `__init__`,无需手动传递。
在 Python 中,__new__ 是实例创建的真正入口——它负责分配内存并返回新对象;而 __init__ 仅负责初始化已存在的实例。因此,当需要控制对象创建流程(例如强制通过特定工厂方法调用),重写 __new__ 是合理选择。但一个常见误区是:试图将用户参数一并传给 super().__new__(cls, ...) ——这会导致 TypeError: object.__new__() takes exactly one argument,因为内置 object.__new__ 仅接受 cls 一个参数。
正确做法是:在自定义 __new__ 中声明所需参数以供签名匹配和逻辑校验,但在调用 super().__new__(cls) 时只传入 cls。Python 解释器会在后续自动将剩余参数(如 myArg)传递给 __init__,无需开发者干预。
以下为修正后的完整示例:
import inspect
class MyObject:
def __new__(cls, myArg):
# 检查调用栈:确认是否由 MyObject.create() 触发
frame = inspect.stack()[1]
if (frame[0].f_locals.get('cls') is cls and
frame[3] == 'create'):
return super().__new__(cls) # ✅ 仅传 cls
else:
raise RuntimeError("To create a new MyObject, use MyObject.create().")
def __init__(self, myArg):
self.myArg = myArg # ✅ myArg 已由 Python 自动传入
@classmethod
async def create(cls, myArg="test"): # ✅ 支持 async(原问题关键需求)
return cls(myArg=myArg)
# 使用示例
obj = MyObject.create()
print(obj.myArg) # 输出: test
# 尝试非法调用会触发异常
# obj2 = MyObject("bad") # RuntimeError: To create...⚠️ 注意事项:
- 参数签名必须一致:__new__ 和 __init__ 的参数名与顺序需严格匹配(除 cls/self 外),否则 __init__ 无法正确接收。
- 避免在 __new__ 中设置实例属性:因对象尚未初始化,此时赋值可能被 __init__ 覆盖或引发状态不一致;应统一在 __init__ 中完成初始化。
- 调用栈检查有局限性:inspect.stack() 性能开销大且依赖实现细节,生产环境建议改用更健壮的机制(如线程局部变量标记、__create_flag 属性等)。
- 异步兼容性:@classmethod + async 本身不改变 __new__ 行为,但确保 create() 返回协程对象,调用方需 await(示例中为简化省略 await,实际应 await MyObject.create())。
总结:__new__ 是对象构造的守门人,其职责是决定是否创建及返回哪个实例;参数传递是 Python 运行时的隐式契约——你只需声明、校验,不必转发。掌握这一机制,即可优雅实现受控实例化与异步工厂模式。

















