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

标签 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 中找到任何对此技术的具体认可。 . “高级使​​用”语言可能是指使用关键字参数(例如 metaclass=),而不是位置参数。我想知道这是偶然发生的还是有意为之。

如果元类是 type 的子类,它确实会失败并返回一个相当有趣的 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
>>>

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

最佳答案

您的问题表述有误:如果继承对象(基类)不是类,那么它们就不是“基类”。关于复合语句的语言文档部分:class says

The inheritance list usually gives a list of base classes

“通常”预示着基类不是类的可能性。话虽如此,该文档似乎继续假设基类并且可以称为“基类”。

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

我发现 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

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

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

必须包括 type() 的子类而不是(只是?)“实例”,因为我们知道它已应用于您的第二个示例。第二个子句(“或基础......”似乎适用于你的第一个例子,但我相信它不会。

当前对类创建的最终答案应该在类型对象中 source .错误信息来自第 2265 行。

关于python - 在 Python 3.x 中,将非类指定为基类是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28445881/

相关文章:

python - Numpy:如何快速替换矩阵中的相等值?

python - 使用批量渲染时如何从屏幕上删除对象(标签、图形)?

c++ - C++中的声明和定义

python - 通过条件语句打印用户输入的三个变量中的最大和第二大数

python - 使用 pyscreenshot 截取元素屏幕截图

Python 3 - 需要从 exec() 返回值

python - 手动投影坐标类似于python中的gluLookAt

python - 如果 python 中的字典是可变的,为什么编辑第二个字典中包含的字典不会更改第二个字典?

c++ - 打印函数地址时 Visual Studio 有问题吗?

c - 别名结构和数组是否合法?