【问题标题】:Assignment inside base class list基类列表中的赋值
【发布时间】:2019-02-15 09:45:39
【问题描述】:

在阅读 typing 模块源代码时,我注意到以下内容:

class _SpecialForm(_Final, _Immutable, _root=True):
    ...

这里,赋值位于基类列表中。

稍后,它被签入:

class _Final:
    def __init_subclass__(self, *args, **kwds):
        if '_root' not in kwds:
            raise TypeError("Cannot subclass special typing classes")

_root 到底去了哪里?文档将其称为“类关键字参数”(https://docs.python.org/3/reference/datamodel.html#object.init_subclass),但我找不到任何进一步的信息。

【问题讨论】:

  • 什么意思?与其他方法一样,如果您不覆盖它,它将最终调用根实现,object.__init_subclass__(它不接受任何关键字参数)。正如文档所描述的那样,它不是一个赋值,而是一个关键字参数。
  • 你已经找到了。它最终成为__init_subclass__ 的参数。 (至少在这种特定情况下。一般来说,它也可以转到元类的__new__。)
  • 所以它实际上唯一的作用就是传递给__init_subclass__?

标签: python python-3.x metaclass


【解决方案1】:

类关键字参数是在类声明中传递的任何关键字参数。只有一个这样的参数有特殊处理 - metaclass= - 这个参数指示将用于提供元类的可调用对象。

那里的任何其他关键字参数按原样传递给元类__new__ 和__init__ 方法,以及任何超类__init_subclass__ 方法。这些没有以特殊方式处理,而且最重要的是,它们不是“基类”——前面提到的方法通常会像任何 Python 方法一样接收这些关键字参数:它们可以在方法签名中声明,或者它们可以接受**kwargs字典(就是这样)。

值得一提的是,在超类中使用适当的__init_subclass__ 方法传递此类参数会“吞下”它,类声明将失败并返回TypeError,因为object 的@ 的参数无法识别987654329@。相比之下,type 类上 __new__ 和 __init__ 的默认元类实现将简单地忽略传递的任何额外关键字。

因此:

In [1]: class A(test=None): 
   ...:     pass 
   ...:            

失败:

TypeError: __init_subclass__() takes no keyword arguments

同时:

In [2]: class A: 
   ...:     def __init_subclass__(cls, **kwd): 
   ...:         super().__init_subclass__(cls)
   ...:                                                                                 

In [3]: class B(A, test=None): 
   ...:     pass 
   ...:           

没有问题。 (A.__init_subclass__ kwd 将通过{"test": None})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    相关资源
    最近更新 更多