在Python 3.6中将ABCMeta与__init_subclass__结合起来时出现TypeError

在Python 3.6中将ABCMeta与__init_subclass__结合起来时出现TypeError

问题描述:

我正在尝试使用python 3.6的新__init_subclass__功能(PEP 487)和abc模块。它似乎没有工作。下面的代码:在Python 3.6中将ABCMeta与__init_subclass__结合起来时出现TypeError

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

产生运行时执行以下操作:如果抽象不使用ABCMeta元类

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' 

,一切工作正常。例如,下面的代码仍然失败,并出现类似的类型错误(大概是因为元类'__new__在类实例化时运行,而父类'__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模块和/或__init_subclass__执行中的错误? (我可能会使用__init_subclass__错误。)有没有人有解决方法?

+4

这是新'__init_subclass__'设计中的一个有趣的交互。几乎所有现存的元类现在都应该将意外的关键字参数传递给'super().__ new__',所以'type .__ new__'可以将它们传递给'__init_subclass__',但是ABCMeta和其他许多元类不会这么做。 – user2357112

+0

对于任何想将'__init_subclass__'和他们无法控制的元类一起使用的人来说,这可能会让人头疼。 – user2357112

+0

我希望这可以起作用,如果你逆转继承的顺序,是否正确?由于'提取者'在'抽象'看到它之前会吃掉'x'。 –

这是abc.ABCMeta中的一个错误,由于__init_subclass__设计中的疣。我建议报告它。

差不多存在每元类现在假设通过对super().__new__所以type.__new__可以将它们传递给__init_subclass__通过意想不到的关键字参数,但是ABCMeta大概吨的其他元类的不这样做呢。 abc.ABCMeta.__new__关键字参数扼流器,而不是传递它,导致你看到的异常。

试图使用__init_subclass__带有尚未更新的新设计的元类的关键字参数不起作用。你必须等待你使用的元类被修补。

+0

谢谢。报告错误:http://bugs.python.org/issue29581 – So8res