Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3.x中,将非类指定为基类是否合法?_Python_Python 3.x_Language Lawyer - Fatal编程技术网

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

在Python3.x中,将非类指定为基类是否合法?,python,python-3.x,language-lawyer,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 '__ma

下面是一个例子:

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

继承列表通常给出基类列表

“通常”预测基不是类的可能性。话虽如此,doc似乎是在假定基是类并且可以称为“基类”的基础上进行的

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

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

如果没有给出基和显式元类,则使用type()

这两个例子都不适用。第二条规则

如果给定了显式元类,但它不是()类型的实例, 然后它被直接用作元类


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

如果将type()的实例作为显式元类给出,或者定义了基,那么将使用最派生的元类

必须包含()类型的子类,而不是(仅?)实例,因为我们知道它应用于第二个示例。第二条(“或基础…”似乎使它适用于你的第一个例子,但我确信它不适用


当前创建类的最终答案应该是type对象。错误消息来自第2265行。

“但我想知道‘instance’应该是‘subclass’还是‘instance or subclass’。否则,这似乎适用于第二个示例,但事实上不适用。”:我不同意。一个“type的实例”只是第二个示例使用的一个类。
isinstance(Meta,type)
返回
True
Meta
被定义为
type
的子类。但是由于type既是子类又是自身的实例(我忘了),Meta也是类型的实例。因此,实例检查实际上是通常理解的“实例或子类”。
>>> 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
>>>