2017-05-08 5 views
2

Normalement, la sous-classe d'une classe que je fais quelque chose commeComment la sous-classe ABCMeta

class Subby(Parenty): 
    def __init__(self): 
     Parenty.__init__(self) 

Mais maintenant, je suis en train de sous-classe une métaclasse, en particulier ABCMeta, donc je fais

import ABCMeta 

class Subby(ABCMeta): 
    def __init__(self): 
     ABCMeta.__init__(self) #this never seems to run 

    def __new__(mcls, name, bases, namespace): 
     cls = ABCMeta.__new__(mcls, name, bases, namespace) 
     return cls 

mais, quand j'essaie alors de sous-classe Subby comme métaclasse comme

class newClass(metaclass=Subby): 
    pass 

Je reçois l'erreur TypeError: __init__() takes 1 positional argument but 4 were given.

Pourquoi est-ce, et comment sous-classe ABCMeta correctement?

+3

'__init__' doit prendre les mêmes arguments que '__new__'. – user2357112

+0

Pouvez-vous instancier 'Subby' tout seul? –

+0

'ABCMeta' est la classe' abc.ABCMeta' ou une autre classe définie dans un autre module? – slackmart

Répondre

3

De l'datamodel:

Si __new__() renvoie une instance de cls, puis __init__() de la nouvelle méthode d'instance sera appelée comme __init__(self[, ...]), où l'auto est la nouvelle instance et les autres arguments sont les mêmes que ceux passés à __new__().

Donc, comme @ user2357112 dit, les signatures doivent correspondre.

Malgré cela, il n'y a vraiment aucune raison de définir __init__ et __new__ si vous voulez simplement créer un ABC. Il suffit de le créer et d'utiliser .register pour enregistrer les classes conformes. Facultativement, créez un certain nombre de méthodes abstraites et un __subclasshook__ qui vérifie la conformité. Un bon exemple existe déjà dans le abc module documentation.

+0

Pour une joyeuse coïncidence, je viens d'écrire une réponse où j'ai effectivement _did_ sous-classe ABCMeta, dans un but. (Je n'avais pas vu cette question auparavant). Je peux être un bon exemple pour cette question - http://stackoverflow.com/a/43884960/108205 – jsbueno