2015-09-03 18 views
7

PyCharm mi avverte Call to __init__ of super class is missedClasse base astratta: aumentare NotImplementedError() in `__init __. Py`?

class AbstractBase(object): 
    def __init__(self): 
     raise NotImplementedError() 

class RealChild(AbstractBase): 
    def __init__(self): 
     #super(RealChild, self).__init__() #### 
     print('do stuff') 

child=RealChild() 

Ma se io lo chiamo, la classe AbstractBase alzerà NotImplementedError.

Io sono una pecora e non so come procedere :-)

+6

Correlato: http://stackoverflow.com/questions/14972631/python-abstract-classes-how-to-discourage-stantening – juanchopanza

risposta

5

Si potrebbe fare qualcosa g tipo-di brutto e verificare il tipo di self nella inizializzazione del tipo astratto per assicurarsi che si è sottotipizzati:

class AbstractBase (object): 
    def __init__ (self): 
     if type(self) is AbstractBase: 
      raise NotImplementedError 

Penso che un approccio più “normale” sarebbe semplicemente non esporre il tipo di base astratto e aspettati che gli utenti non lo creino.

+0

Come posso "non esporre il tipo di base astratto"? Altri sviluppatori hanno bisogno di sottoclasse. – guettli

+0

Gli sviluppatori sì, ma gli utenti no. Quindi, rendilo disponibile solo agli sviluppatori che sanno che non dovrebbe essere istanziato da solo. In generale, non andare troppo lontano per applicare le regole, ma solo documentarlo chiaramente e aspettarti che le persone lo facciano correttamente. – poke

+0

Ancora non capisco. I miei utenti sanno come usare un browser web. Il non so che Python è un linguaggio di programmazione. Immagino che "non esporre il tipo di base astratto" non funzioni nel mio caso. – guettli

0

Nella classe astratta sostituire l'eccezione nella funzione init con

pass 

Questa eccezione è usato per prevenire dall'inizializzazione della nuova istanza della classe astratta (è astratta, quindi non puoi) Quindi usa 'pass' o non ascoltare pycharm e non chiamare super

+2

Tecnicamente, l'eccezione impedisce di inizializzare un nuovo oggetto, non di crearlo. 'a = A .__ new __ (A)' funziona bene. – chepner

4

Si potrebbe considerare using the abc Abstract Base Class module per contrassegnare __init__ come astratto, e poi andare avanti e richiamare la superclasse __init__ dalla sottoclasse (e, come DorElias suggested, dare la superclasse __init__ un'implementazione banale di pass):

from abc import ABCMeta, abstractmethod 


class AbstractBase(object, metaclass=ABCMeta): 
    @abstractmethod # This method must be overridden... 
    def __init__(self): 
     print("...but can still be called via super by subclasses have shared construction logic") 
     pass 


class RealChild(AbstractBase): 
    def __init__(self): 
     super().__init__() # Won't do anything, UNTIL the day you decide all subclasses of AbstractBase need shared logic 
     print('do stuff') 


child = RealChild() 

Se si tenta di creare un'istanza tramite parent = AbstractBase() o parent = AbstractBase.__new__(AbstractBase), si otterrà un errore:

TypeError: Can't instantiate abstract class AbstractBase with abstract methods init

Quindi hai la tua sicurezza astratta e irrealizzabile, ma allo stesso tempo sei ancora ben predisposto per alterare tutte le costruzioni di classe dei bambini modificando la costruzione della classe base, come è giusto e corretto.

+0

Questa dovrebbe essere la risposta accettata. Se l'intento è di avere un ABC, sii esplicito al riguardo - sollevare un'eccezione nel costruttore non è il modo di farlo. – BoltzmannBrain

Problemi correlati