问题
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