TypeError when combining ABCMeta with __init_subclass__ in Python 3.6

旧时模样 提交于 2020-12-08 05:30:21

问题


I'm trying to use python 3.6's new __init_subclass__ feature (PEP 487) with the abc module. It doesn't seem to be working. The following code:

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

yields the following when run:

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'

Everything works fine if Abstracted doesn't use the ABCMeta metaclass.

This error is fairly resilient, for example, the following code still fails with a similar type error (presumably because a metaclass' __new__ runs at class instantiation time, whereas the parent class' __new__ doesn't run until object instantiation).

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

Can anyone confirm that this is a bug in the Python 3.6 abc module and/or __init_subclass__ implementation? (I might be using __init_subclass__ wrong.) Does anyone have a workaround?


回答1:


It's a bug in abc.ABCMeta, due to a wart in the design of __init_subclass__. I recommend reporting it.

Pretty much every metaclass in existence is now supposed to pass unexpected keyword arguments through to super().__new__ so type.__new__ can pass them to __init_subclass__, but ABCMeta and probably tons of other metaclasses don't do that yet. abc.ABCMeta.__new__ chokes on the x keyword argument instead of passing it through, causing the exception you see.

Trying to use __init_subclass__ keyword arguments with a metaclass that hasn't been updated for the new design isn't going to work. You'll have to wait for the metaclasses you use to be patched.



来源:https://stackoverflow.com/questions/42281697/typeerror-when-combining-abcmeta-with-init-subclass-in-python-3-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!