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

这是一个例子:

>>> 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'>,)
>>> 

我对课堂陈述特别感兴趣.虽然这似乎有效,但我在language reference中找不到对此技术的任何具体认可.“高级用途”语言可能指的是使用关键字参数(例如metaclass =),而不是位置参数.我想知道这是偶然还是设计.

如果元类是类型的子类,它确实失败了一个相当有趣的TypeError,如elsewhere in the reference所讨论的:

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

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

最佳答案 你的问题有点误解:如果继承对象(基础)不是类,它们不是“基类”.关于复合语句的语言doc部分:class说

The inheritance list usually gives a list of base classes

“通常”预计基数不是阶级的可能性.话虽如此,文档似乎继续假设基础是类,可以称为“基类”.

您的示例表明可以实现这种可能性. “高级用途”中的“数据模型:自定义类创建”部分(3.3.3中的3.4)详细介绍了类语句的工作原理.相关步骤是第一个,确定元类和最后一个,调用元类.

我发现3.3.3.1,“确定适当的元类”有点不清楚.第一条规则

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

似乎适用于你的第一个例子.但我想知道’instance’应该是’subclass’还是’instance或subclass’.否则,这似乎适用于您的第二个示例,但事实并非如此.第三条规则

if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used

必须包含type()的子类而不是(只是?)’instances’,因为我们知道它已应用于你的第二个例子.第二个条款(“或基础……”似乎使它适用于你的第一个例子,但我确信它没有.

当前对类创建的确定答案应该在类型对象source中.错误消息来自第2265行.

点赞