理解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
相关产品推荐
相关产品推荐

