2015-09-09 11 views
10

Ho un codice Python che copre diversi file che ho impacchettato per comodità, finendo con i seguenti 3 file nella directory my_package:autoreload e package che causano TypeError: super (type, obj): obj deve essere un'istanza o sottotipo di tipo

__init__.py 

contenuti:

from file1 import * 
from file2 import * 

contenuti file1.py:

class Base(object): 
    pass 

file2.p Contenuti y:

from file1 import Base 
class Derived(Base): 
    def __init__(self): 
     return super(Derived, self).__init__() 

ho quindi eseguire in IPython:

>>>%autoreload 2 
>>>import my_package 
>>>t = my_package.Derived() 

Fin qui tutto bene. Ma poi apporto le modifiche a file2.py, ad esempio aggiungendo un attributo dummy. Ora, quando eseguo:

>>>t = my_package.Derived() 
>>>  2 class Derived(Base): 
>>>  3  def __init__(self): 
>>>----> 4   return super(Derived, self).__init__() 
>>>  5 
>>>  6 dumm = 'asdf' 
>>> 
>>>TypeError: super(type, obj): obj must be an instance or subtype of type 

Questo non va via fino a che non riavviare la console IPython. Perché il caricamento automatico non si occupa correttamente di questo? Tutto funziona se metto Base e Derivato in un singolo file di modulo piuttosto che in un pacchetto.

risposta

6

Non sono un utente di IPython, quindi non posso dire esattamente cosa sta succedendo, ma suppongo che questo sia un sintomo dell'utilizzo di from file2 import * nel file __init__.py.

Quando si crea un'istanza della classe Derived utilizzando package.Derived, non stai ricevendo la versione più recente della classe, ma è stato eseguito la vecchia versione che era corrente quando il pacchetto è stato caricato per la prima e la dichiarazione from file2 import * . Quando hai modificato il codice del modulo e IPython lo ha ricaricato, questo ha cambiato package.file2.Derived, ma non package.Derived.

Tuttavia, la vecchia versione della classe ha ancora un riferimento al suo spazio dei nomi del modulo, e quando cerca di cercarsi per nome nella chiamata super, trova invece la versione più recente della classe. Questo è il motivo per cui si verifica un errore, poiché le due classi Derived non corrispondono.

Probabilmente si eviterà questo problema se si accede direttamente a package.file2.Derived. Questo ti porterà sempre alla versione corrente della classe che non dovrebbe avere problemi con le chiamate super. Nota che se ci sono ancora delle istanze della classe che sono state create prima di aver modificato il modulo, potresti ancora avere dei problemi (ma probabilmente non è molto sorprendente).

+2

Questo ha senso. Ho provato a usare "da file2 import Derived" piuttosto che a *, ma purtroppo non è stato risolto. È strano che autoreload non riesca a capire quel pacchetto. Dovrebbe essere aggiornato. – Leo

+0

@Leo L'errore sembra verificarsi quando si utilizza 'da A.B import C' se B contiene un file' __init __. Py'. Questo mi infastidisce troppo. – Edityouprofile