以下是一个例子:
>>> def magic(name, bases, dct):
... print(repr(bases))
... return type(name, (object,), dct)
...
>>> class Foo('hello world!', metaclass=magic):
... pass
...
('hello world!',)
>>> Foo
<class '__main__.Foo'>
>>> Foo.__bases__
(<class 'object'>,)
>>>
我对class
声明特别感兴趣。虽然这似乎有效,但我无法在language reference中找到对此技术的任何具体认可。 &#34;高级用途&#34;语言可能是指使用关键字参数(例如metaclass=
),而不是位置参数。我想知道这是偶然还是设计的。
如果元类是TypeError
的子类,如elsewhere in the reference所讨论的那样type
,它确实失败了。{/ p>
>>> class Meta(type):
... def __new__(mcs, name, bases, dct):
... print(repr(bases))
... bases = (object,)
... return super().__new__(mcs, name, bases, dct)
... def __init__(cls, name, bases, dct):
... super().__init__(name, (object,), dct)
...
>>> class Foo('hello world!', metaclass=Meta):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
>>>
总结:何时(如果有的话)将非类作为基类传递是合法的?
答案 0 :(得分:2)
您的问题略有错误:如果继承对象(基础)不是类,则它们不是基类&#39;。复合语句的语言doc部分:class
继承列表通常提供基类列表
&#39;一般&#39;预计基数不是阶级的可能性。话虽如此,文档似乎继续假设基础是类,并且可以被称为基类&#39;。
您的示例表明可以实现这种可能性。数据模型:自定义类创建部分(3.4.3中的3.3.3)&#34;高级用途&#34;详细介绍了类声明的工作原理。相关步骤是第一个,确定元类和最后一个,调用元类。
我发现3.3.3.1,&#34;确定适当的元类&#34;有点不清楚。第一条规则
如果没有给出碱基且没有明确的元类,则使用type()
不适用于您的任何一个示例。第二条规则
如果给出了显式元类并且它不是type()的实例, 然后它直接用作元类
似乎适用于您的第一个示例。但我想知道是否&#39;实例&#39;应该是&#39;子类&#39;或者&#39;实例或子类&#39;。否则,这似乎适用于您的第二个示例,但事实并非如此。第三条规则
如果给出了类型()的实例作为显式元类,或者定义了基数,则使用最派生的元类
必须包含type()的子类而不是(只是?)&#39;实例&#39;,因为我们知道它已应用于您的第二个示例。第二个条款(&#34;或基础......&#34;似乎会使它适用于你的第一个例子,但我确信它没有。
当前对类创建的明确答案应该在类型对象source中。错误消息来自第2265行。