在 Python 3.6 中将 ABCMeta 与 __init_subclass__ 组合时出现 TypeError

TypeError when combining ABCMeta with __init_subclass__ in Python 3.6

我正在尝试将 python 3.6 的新 __init_subclass__ 功能 (PEP 487) 与 abc 模块一起使用。它似乎没有用。以下代码:

from abc import ABCMeta
class Initifier:
    def __init_subclass__(cls, x=None, **kwargs):
        super().__init_subclass__(**kwargs)
        print('got x', x)

class Abstracted(metaclass=ABCMeta):
    pass

class Thingy(Abstracted, Initifier, x=1):
    pass

thingy = Thingy()

在 运行 时产生以下结果:

Traceback (most recent call last):
  File "<filename>", line 10, in <module>
    class Thingy(Abstracted, Initifier, x=1):
TypeError: __new__() got an unexpected keyword argument 'x'

如果 Abstracted 不使用 ABCMeta 元class,一切正常。

这个错误是相当有弹性的,例如,下面的代码仍然失败并出现类似的类型错误(大概是因为 metaclass' __new__ 运行s 在 class 实例化时间,而父 class' __new__ 直到对象实例化才 运行。

from abc import ABCMeta

class Initifier:
    def __new__(cls, name, bases, dct, x=None, **kwargs):
        return super().__new__(cls, name, bases, dct, **kwargs)

    def __init_subclass__(cls, x=None, **kwargs):
        super().__init_subclass__(**kwargs)
        print('got x', x)

class Abstracted(metaclass=ABCMeta):
    pass

class Thingy(Initifier, Abstracted, x=1):
    pass

thingy = Thingy()

谁能确认这是 Python 3.6 abc 模块 and/or __init_subclass__ 实现中的错误? (我可能使用 __init_subclass__ 错误。)有人有解决方法吗?

这是 abc.ABCMeta 中的一个错误,因为 __init_subclass__ 的设计存在瑕疵。我建议举报。

现在几乎所有存在的元类都应该将意外的关键字参数传递给 super().__new__,因此 type.__new__ 可以将它们传递给 __init_subclass__,但是 ABCMeta 和可能大量的其他元类不要那样做。 abc.ABCMeta.__new__x 关键字参数上阻塞而不是传递它,导致你看到的异常。

尝试将 __init_subclass__ 关键字参数与尚未针对新设计​​更新的元类一起使用是行不通的。您将不得不等待您使用的元类被修补。