在Python 3.x中,将非类指定为基类是否合法?

时间:2015-02-11 03:04:45

标签: python python-3.x language-lawyer

以下是一个例子:

>>> 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
>>>

总结:何时(如果有的话)将非类作为基类传递是合法的?

1 个答案:

答案 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行。