在什么情况下调用父类中的多个元类?

2024-06-16 04:51:24 发布

您现在位置:Python中文网/ 问答频道 /正文

行为怪异的代码(用Python2.7.3测试):

class Meta1(type):
   def __new__(mcl, name, bases, attrs):
        print "Hello Meta1.__new__ "
        return super(Meta1, mcl).__new__(mcl, name, bases, attrs)

class Meta2(type):
    def __new__(mcl, name, bases, attrs):
        print "Hello Meta2.__new__ "
        return super(Meta2, mcl).__new__(
            type, # looks to cause all strange behavior, but anyway pass type here, not mcl
            name, bases, attrs)

print "Declaring BaseClass1"
class BaseClass1(object):
    __metaclass__ = Meta1

print "-----------------------"
print "Declaring BaseClass2"
class BaseClass2(BaseClass1):
    __metaclass__ = Meta2

print "-----------------------"
print BaseClass2.__class__

其输出:

^{pr2}$

关于准则的问题:

为什么在BaseClass2的__metaclass__属性被设置为Meta2,并且对于它的父类BaseClass1,__metaclass__属性被设置为Meta1,而Meta1-no-Meta2都不是另一个类的子类,为什么定义BaseClass2没有任何问题?在

为什么在BaseClass2定义中Meta2.__new__和{}都被调用?在

在什么情况下调用父类的元类中的方法?

长话短说:

在试图理解我们项目中的元类是如何工作的时候,我精心设计了上面可以找到的代码。(该项目使用Python2.7.3,看起来项目中使用的元类是合理的,因为它们用于向用户提供API,而元类在幕后为用户做了很多事情。)

首先,我试图找到关于元类如何与继承一起工作的文档。下面由Guido van Rossum撰写的文章(相当古老,但似乎对python2.7有效)阐明了在继承的情况下如何选择元类,对子类的元类有什么要求,以及Python在为同级类选择元类时可以执行的小技巧:https://www.python.org/download/releases/2.2.3/descrintro/。本文和我在Python中读到的关于元类的文章并不能解释我所观察到的行为。我想阅读Python解释器代码会有所启发,但我相信文档的力量,并希望这种极端的措施可以避免。欢迎对描述所观察到的代码行为的材料的任何答案/指针。在


Tags: 项目代码namenewtypeattrsclassmetaclass
1条回答
网友
1楼 · 发布于 2024-06-16 04:51:24

找了很多遍之后,我想我找到了答案。Python3文档中有一个section这样说。在

3.3.3.3. Determining the appropriate metaclass

The appropriate metaclass for a class definition is determined as follows:

  • if no bases and no explicit metaclass are given, then type() is used
  • if an explicit metaclass is given and it is not an instance of type(), then it is used directly as the metaclass
  • if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used

The most derived metaclass is selected from the explicitly specified metaclass (if any) and the metaclasses (i.e. type(cls)) of all specified base classes. The most derived metaclass is one which is a subtype of all of these candidate metaclasses. If none of the candidate metaclasses meets that criterion, then the class definition will fail with TypeError.

我认为这同样适用于Python2(无论如何是v2.7),尽管我在它的文档中找不到类似于上面的内容。在

BaseClass2定义同时调用Meta2.__new__()Meta1.__new__()的原因很简单,Meta2.__new__()显式地通过对super()的调用来调用它。但是,要使其正常工作,还需要更改Meta2.__new__(),这样它将返回super(Meta2, mcl).__new__(mcl, name, bases, attrs),而不是{}。在

相关问题 更多 >