行为怪异的代码(用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解释器代码会有所启发,但我相信文档的力量,并希望这种极端的措施可以避免。欢迎对描述所观察到的代码行为的材料的任何答案/指针。在
找了很多遍之后,我想我找到了答案。Python3文档中有一个section这样说。在
我认为这同样适用于Python2(无论如何是v2.7),尽管我在它的文档中找不到类似于上面的内容。在
BaseClass2
定义同时调用Meta2.__new__()
和Meta1.__new__()
的原因很简单,Meta2.__new__()
显式地通过对super()
的调用来调用它。但是,要使其正常工作,还需要更改Meta2.__new__()
,这样它将返回super(Meta2, mcl).__new__(mcl, name, bases, attrs)
,而不是{相关问题 更多 >
编程相关推荐