Domanda

Ho una classe ereditata e sovrascritta un metodo che è anche ereditato da una classe base.Ma la cosa è che il metodo centrale crea un'eccezione che vorrei bypassare chiamando il primo metodo dichiarato.C'è un modo per specificare il MRO che ignora le seconde chiamate?

Un esempio potrebbe essere:

class Base(object):
     def __init__(self):
         res = "Want this"
         print res

class BaseA(Base):
      def __init__(self):
          res = super(BaseA, self).__init__()
          res = "Not this"
          print res

class BaseB(BaseA):
      def __init__(self):
          res = super(BaseB, self).__init()
          #At this poing res is "Not this"
          #The desire is that it would be "Want this"
          print res
.

Grazie mille

PD: Qualcosa come la classe baseb (base, basea) potrebbe funzionare?

È stato utile?

Soluzione

Normalmente si risolve il metodo.

Tuttavia, il primo argomento a super() è il posto dove iniziare la ricerca del metodo successivo da .Normalmente sarebbe la classe attuale, ma puoi anche passare nella classe base:

class BaseB(BaseA):
    def __init__(self):
        res = super(BaseA, self).__init__()
.

Qui, super() prende la MRO di type(self), trova BaseA in quella MRO e cerca la prossima esecuzione della classe Implementazione __init__.

Un altro modo per bypassare il metodo problematico __init__ è quello di chiamare direttamente il metodo non legato su Base direttamente:

class BaseB(BaseA):
    def __init__(self):
        res = Base.__init__(self)
.

Bypassare qualsiasi MRO cerca interamente.

Altri suggerimenti

Il modo giusto per risolvere questo è creare una nuova gerarchia di classe che sovrascrive il metodo di offensivo con un'implementazione migliorata.Se insisti sul hackery, però, questo potrebbe essere quello che vuoi:

class BaseB(BaseA):
      def __init__(self):
          res = super(BaseA, self).__init()
          #At this poing res is "Not this"
          #The desire is that it would be "Want this"
          print res
.

Nota che sto chiedendo la super implementazione rispetto alla Basea, il che significa che l'implementazione della Basea non viene mai utilizzata.


.

Tuttavia, questo può fare la cosa sbagliata quando è coinvolta l'ereditarietà del diamante.Considera:

class Base(object):
    def __init__(self):
        print 'initing Base'

class BaseA(Base):
    def __init__(self):
        print 'initing BaseA'
        res = super(BaseA, self).__init__()

class BaseB(BaseA):
    def __init__(self):
        print 'initing BaseB'
        res = super(BaseA, self).__init__()

class BaseC(BaseA):
    def __init__(self):
        print 'initing BaseC'
        res = super(BaseC, self).__init__()

class BaseD(BaseB, BaseC):
    def __init__(self):
        print 'initing BaseD'
        res = super(BaseD, self).__init__()

print BaseD()
.

L'output è:

initing BaseD
initing BaseB
initing Base
<__main__.BaseD object at 0x7f1e693a0110>
.

BaseC è stato saltato anche se non è quello che volevamo.Questo perché BaseC è arrivato tra BaseB e BaseA nell'ordine del metodo di risoluzione, quindi quando abbiamo saltato da BaseB a BaseA abbiamo inavvertitamente trascurato BaseC.

>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
.

Come BOUT

Base.__init__(self)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top