Próbuję użyć nowej funkcji Pythona 3.6 __init_subclass__
(PEP 487) z modułem abc
. Wygląda na to, że nie działa. Poniższy kod:TypeError przy łączeniu ABCMeta z __init_subclass__ w Pythonie 3.6
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()
otrzymuje się po uruchomieniu następuje:
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'
Wszystko działa dobrze, jeśli Abstracted nie używa ABCMeta
metaklasa.
Ten błąd jest dość elastyczna, na przykład, poniższy kod nie powiedzie się z podobnym błędem typu (prawdopodobnie dlatego, że metaklasa __new__
biegnie w czasie klasa konkretyzacji, natomiast klasy nadrzędnej __new__
nie działa aż obiektu instancji) .
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()
Czy ktoś może potwierdzić, że jest to błąd w Pythonie 3.6 abc
modułu i/lub __init_subclass__
realizacji? (Być może nieprawidłowo używam __init_subclass__
.) Czy ktoś ma obejście tego problemu?
To zabawna interakcja w nowym projekcie "__init_subclass__". Prawie każdy istniejący metaclass ma teraz przekazywać nieoczekiwane argumenty ze słowem kluczowym do "super() .__ nowy__", więc 'type .__ new__' może przekazać je do' __init_subclass__', ale ABCMeta i prawdopodobnie tony innych metaclasses tego nie robią . – user2357112
Prawdopodobnie przez pewien czas będzie to ból głowy dla każdego, kto chce używać '__init_subclass__' razem z metaklasem, nad którym nie mają kontroli. – user2357112
Spodziewam się, że to zadziała, jeśli odwrócisz porządek dziedziczenia, prawda? Ponieważ 'Initifier' będzie jadł' x' zanim zobaczy go 'Abstracted'. –