python 元类的继承_python – 元类的继承

本文深入探讨了Python2中`__metaclass__`的特殊性质,解释了其在类创建过程中的作用,以及在类体中不同使用场景下的行为。重点讲解了元类的__new__方法如何决定类的行为,并通过实例展示了元类选择和类型调用的区别。
摘要由CSDN通过智能技术生成

你猜测很多,而Python的极简主义和“特殊情况不足以破坏规则”.指令,让它更容易理解.

在Python2中,类主体中的__metaclass__属性在类创建时用于调用类所属的“类”.通常它是名为type的类.为了澄清,那一刻是在解析器解析了类体之后,在编译器将其编译为代码对象之后,以及在程序运行时实际运行之后,并且只有在该类体中明确提供了__metaclass__之后.

所以让我们检查方式如下:

class A(object):

__metaclass__ = MetaA

class B(A):

pass

A在其正文中有__metaclass__ – 调用MetaA而不是类型,使其成为“类对象”.

B的体内没有__metaclass__.创建它之后,如果你只是尝试访问__metaclass__属性,那么它就是一个属性,它将是可见的,因为Python将从超类A中获取它.如果你检查A .__ dict__,你会看到__metaclass__,如果你检查B .__ dict__没有.

创建B时,根本不使用此A .__ metaclass__属性.如果在声明之前在A中更改它仍然会使用与A相同的元类 – 因为Python确实使用父类的类型作为元类,而忽略了显式__metaclass__的声明.

为了显示:

In [1]: class M(type): pass

In [2]: class A(object): __metaclass__ = M

In [3]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(A.__class__, A.__metaclass__, A.__dict__.get("__metaclass__"), type(A))

class: , metaclass_attr: , metaclass_in_dict: , type:

In [4]: class B(A): pass

In [5]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(B.__class__, B.__metaclass__, B.__dict__.get("__metaclass__"), type(B))

class: , metaclass_attr: , metaclass_in_dict: None, type:

In [6]: A.__metaclass__ = type

In [8]: class C(A): pass

In [9]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(C.__class__, C.__metaclass__, C.__dict__.get("__metaclass__"), type(C))

class: , metaclass_attr: , metaclass_in_dict: None, type:

此外,如果您尝试通过调用类型而不是使用带有类语句的主体来创建类,则__metaclass__也只是一个普通属性:

In [11]: D = type("D", (object,), {"__metaclass__": M})

In [12]: type(D)

type

总结到目前为止:Python 2中的__metaclass__属性只有在显式放置在类主体声明中时才是特殊的,作为执行类块语句的一部分.它是一个普通的属性,之后没有特殊的属性.

Python3都摆脱了这个奇怪的“__metaclass__属性现在不好”,并允许通过更改语法来指定元类来进一步自定义类体. (就像在类声明本身上声明它是一个“元类命名参数”)

现在,对于提出疑问的第二部分:如果在元类的__new__方法中调用类型而不是类型.__ new__,则Python无法“知道”类型是从派生元类调用的.当你调用type .__ new__时,你传递你的元类的__new__本身被运行时传递的cls属性作为它的第一个参数:这就是将结果类标记为类的子类的实例.这就像继承适用于Python中的任何其他类一样 – 所以“没有特殊行为”:

所以,发现差异:

class M1(type):

def __new__(metacls, name, bases, attrs):

cls = type.__new__(metacls, name, bases, attrs)

# cls now is an instance of "M1"

...

return cls

class M2(type):

def __new__(metacls, name, bases, attrs):

cls = type(cls, name, bases, attrs)

# Type does not "know" it was called from within "M2"

# cls is an ordinary instance of "type"

...

return cls

可以在交互式提示中看到:

In [13]: class M2(type):

....: def __new__(metacls, name, bases, attrs):

....: return type(name, bases, attrs)

....:

In [14]: class A(M2): pass

In [15]: type(A)

Out[15]: type

In [16]: class A(M2): __metaclass__ = M2

In [17]: A.__class__, A.__metaclass__

Out[17]: (type, __main__.M2)

(请注意,元类__new__方法的第一个参数是元类本身,因此比代码中的cls更恰当地命名为metacls,并且在“野外”中有很多代码)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值