2015-07-01 13 views
7

La classe child eredita dalla classe parent. All'interno del costruttore di child sto inizializzando una variabile membro list di tipo xs ripetutamente chiamando la funzione membro foo() definita in parent. Si scopre che se inizializzo xs eseguendo il loop e aggiungendo in modo esplicito ogni valore restituito da foo(), tutto funziona correttamente.Impossibile chiamare il metodo del genitore nella comprensione dell'elenco nell'inizializzatore del child, ma il ciclo esplicito funziona

Tuttavia, se provo a fare la stessa cosa all'interno di una lista di comprensione, ottengo uno strano errore lanciato contro di me. Perché si verifica questo errore? Qual è la differenza tra una comprensione delle liste in questo caso e il ciclo esplicito?

Il MWE per il codice che funziona:

class parent(object): 
    def __init__(self): 
     self.x = 5 

    def foo(self, a): 
     return self.x 


class child(parent): 
    def __init__(self): 
     super().__init__() 

     self.xs = [] 
     for i in range(9): 
      self.xs.append(super().foo(i))  

mychild = child() 

La definizione di child ma con la lista di comprensione:

class child(parent): 
    def __init__(self): 
     super().__init__() 
     self.xs = [super().foo(i) for i in range(9)] 

L'errore in questione:

% python test.py 
Traceback (most recent call last): 
    File "test.py", line 20, in <module> 
    mychild = child() 
    File "test.py", line 17, in __init__ 
    self.xs = [super().foo(i) for i in range(9)] 
    File "test.py", line 17, in <listcomp> 
    self.xs = [super().foo(i) for i in range(9)] 
TypeError: super(type, obj): obj must be an instance or subtype of type 
zsh: exit 1  python test.py 

risposta

6

Lista le comprensioni sono effettivamente eseguite in un ambito separato (vedi ad esempio Why is one class variable not defined in list comprehension but another is?), quindi la forma implicita di super senza argomenti non funzionerà nella comprensione della lista.

si hanno due opzioni, partendo dal presupposto che non si vuole tornare allo standard for ciclo:

  1. Utilizzare la forma esplicita di super, passando gli argomenti di classe e istanza: super(child, self).foo(i); oppure
  2. Come hai ereditato foo da parent, basta chiamarlo sull'istanza: self.foo(i).
Problemi correlati