元类中__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中,
desc是在类对象被创建之前就加入到属性字典attrs中,相当于类定义时原生声明的方法,属于类的固有属性,存在于类的__dict__中。 - 示例2中,
desc是在类对象创建完成后直接赋值给类对象,属于动态添加的类属性,同样在类的__dict__中,但不属于类定义阶段的原始内容。
- 示例1中,
继承行为差异
- 如果有子类继承
Bar,示例1中的desc会被子类继承(子类创建时会继承父类的属性字典,desc已经是父类属性字典的一部分)。 - 示例2中的
desc不会被子类默认继承,因为它是父类对象创建后动态添加的属性,子类的属性字典里不会包含它,除非子类的元类也在__init__中做同样赋值,或者子类显式继承该属性。
- 如果有子类继承
属性可追溯性
- 示例1中的
desc可以通过类的__dict__或dir()方法,明确看到它是类定义的一部分;示例2中的desc虽然也能查到,但属于后续附加的属性,不属于类定义的原始内容。
- 示例1中的
内容的提问来源于stack exchange,提问作者2018 dfwe
相关产品推荐
相关产品推荐

