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