You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

理解Python中__init__与__new__的类创建及参数传递问题

Python中__new__与__init__的调用逻辑及参数修改方案

核心问题解答

  • __init__的调用者:由Python解释器自动调用。当创建类实例时,解释器先调用__new__创建对象,若__new__返回当前类(或其子类)的实例,解释器会立即调用该实例的__init__方法。
  • __init__使用的参数:默认是创建实例时传入的原始参数,和__new__内部调用父类__new__时传入的参数无关。

你的代码问题分析

第一个代码示例

你在BigPoint.__new__中给Point.__new__传入了[2300, 7800],但这只是修改了传给__new__的参数,__init__依然会使用创建实例时的(1000, 1000, kw=True)执行,所以最终_x和_y还是1000。

第二个代码示例

你在Point.__new__中直接给实例的_x赋值2300,但随后__init__方法会执行self._x = x(这里的x是原始参数1000),覆盖掉__new__中设置的值,所以结果依然不变。

实现参数修改并让__init__使用的方案

要让__init__使用修改后的参数,有两种常用方式:

方式1:重写__init__方法,在子类中修改参数后调用父类__init__

这是最直观且推荐的方式,直接在初始化阶段调整参数:

class Point:
    def __new__(cls, *args, **kwargs):
        print(args, kwargs)
        return super().__new__(cls)

    def __init__(self, x, y, kw=False):
        self._x = x
        self._y = y
        self._kw = kw

class BigPoint(Point):
    def __init__(self, x, y, kw=False):
        # 修改参数后调用父类__init__
        super().__init__(2300, 7800, kw)

bp = BigPoint(1000, 1000, kw=True)
print(bp.__dict__)  # 输出: {'_x': 2300, '_y': 7800, '_kw': True}

方式2:在__new__中传递修改后的参数,配合__init__读取临时属性

如果需要在__new__阶段处理参数,可以将修改后的值存入实例临时属性,再在__init__中优先使用这些值:

class Point:
    def __new__(cls, *args, **kwargs):
        print(args, kwargs)
        p = super().__new__(cls)
        # 把修改后的参数存入临时属性
        p._override_args = (2300, 7800)
        return p

    def __init__(self, x, y, kw=False):
        # 优先使用临时属性的参数,无则用原始参数
        x, y = getattr(self, '_override_args', (x, y))
        self._x = x
        self._y = y
        self._kw = kw
        # 清理临时属性
        del self._override_args

class BigPoint(Point):
    pass

bp = BigPoint(1000, 1000, kw=True)
print(bp.__dict__)  # 输出: {'_x': 2300, '_y': 7800, '_kw': True}

内容的提问来源于stack exchange,提问作者Michael Schäfer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:55:08