2017-02-16 14 views
8

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?

+4

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

+0

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

+0

Spodziewam się, że to zadziała, jeśli odwrócisz porządek dziedziczenia, prawda? Ponieważ 'Initifier' będzie jadł' x' zanim zobaczy go 'Abstracted'. –

Odpowiedz

6

To błąd w abc.ABCMeta, ze względu na brodawkę w projekcie __init_subclass__. Polecam to zgłosić.

Prawie każdy metaklasa w istnieniu jest teraz powinien przechodzić przez nieoczekiwane słowa kluczowe argumenty do super().__new__ tak type.__new__ można przekazać je do __init_subclass__, ale ABCMeta i pewnie mnóstwo innych metaclasses nie rób tego jeszcze. abc.ABCMeta.__new__ dławiki na argumencie słowa kluczowego x zamiast go przekazywać, powodując wyjątek, który widzisz.

Próba użycia argumentów słów kluczowych z metaclass, który nie został zaktualizowany dla nowego projektu, nie będzie działać. Musisz poczekać, aż metaclasy, których używasz, zostaną załatane.

+0

Dzięki. Zgłoszono błąd: http://bugs.python.org/issue29581 – So8res

Powiązane problemy