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

元类中__new__与__init__方法有何区别?属性添加差异何在?

元类中__new__与__init__的区别及属性添加差异

问题1:元类中的__new__和__init__方法有何区别?

元类是用来创建类的“类”,这两个方法的核心差异在于执行时机和作用对象:

  • __new__方法:是类对象的构造器,在类对象被创建之前执行。它的第一个参数是元类本身(cls),接收类名、父类元组、属性字典三个参数,负责生成并返回新的类对象。你可以在这个阶段修改属性字典,再传给父类的__new__来定制最终创建的类。
  • __init__方法:是类对象的初始化器,在类对象已经被创建(即__new__返回了类对象)之后执行。它的第一个参数是已经创建好的类对象(self),同样接收类名、父类元组、属性字典,作用是给已存在的类对象做后续初始化操作,比如添加属性、修改配置等。

特别注意:只有当__new__返回了属于该元类的对象时,__init__才会被调用;如果__new__返回其他类型的对象,__init__不会执行。

问题2:在__new__中添加desc属性与在__init__中添加有何区别?二者执行结果看似一致。

直接调用b = Bar(); print(b.desc())确实都会输出the test,但二者本质差异很明显,先看你给出的两段代码:

代码示例1(__new__中添加属性)

class MyMeta(type):
    def __init__(self, name, bases, attrs):
        pass
        
    def __new__(cls, name, bases, attrs):
        attrs['desc'] = lambda self: "the test"
        return super().__new__(cls, name, bases, attrs)

代码示例2(__init__中添加属性)

class MyMeta(type):
    def __init__(self, name, bases, attrs):
        self.desc = lambda self: "the test"

    def __new__(cls, name, bases, attrs):
        return super().__new__(cls, name, bases, attrs)

核心差异点:

  1. 属性添加时机

    • 示例1中,desc是在类对象被创建之前就加入到属性字典attrs中,相当于类定义时原生声明的方法,属于类的固有属性,存在于类的__dict__中。
    • 示例2中,desc是在类对象创建完成后直接赋值给类对象,属于动态添加的类属性,同样在类的__dict__中,但不属于类定义阶段的原始内容。
  2. 继承行为差异

    • 如果有子类继承Bar,示例1中的desc会被子类继承(子类创建时会继承父类的属性字典,desc已经是父类属性字典的一部分)。
    • 示例2中的desc不会被子类默认继承,因为它是父类对象创建后动态添加的属性,子类的属性字典里不会包含它,除非子类的元类也在__init__中做同样赋值,或者子类显式继承该属性。
  3. 属性可追溯性

    • 示例1中的desc可以通过类的__dict__或dir()方法,明确看到它是类定义的一部分;示例2中的desc虽然也能查到,但属于后续附加的属性,不属于类定义的原始内容。

内容的提问来源于stack exchange,提问作者2018 dfwe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:42:59