2012-01-22 3 views
7

Ho un errore di importazione divertente quando utilizzo Inheritence in Python.Python Child non può utilizzare un modulo importato dal genitore

In una classe genitore imparo il modulo sqlite3, in una classe figlio, quindi proverò ad usare una funzione sqlite3 ma ricevo un errore che dice "NameError: nome globale 'sqlite3' non è definito". Perché ciò accade & come si risolve?

Le 2 classi sono in file separati:

Parent.py

import sqlite3 

class Parent: 
    def __init__(self): 

     self.create_database() 

    def create_database(self): 
     """ Virtual function to be overriden in child classes """ 
     pass 

    ...more class functions that use sqlite3 functions 

Child.py

import Parent 

class Child(Parent.Parent): 
    def create_database(self): 
     self.db = sqlite3.connect("test.db") # Error occurs HERE 

c = Child() 

risposta

12

il modulo sqlite3 viene importato nel modulo padre da cui è necessario accedere tramite quel modulo

self.db = Parent.sqlite3.connect("test.db") 

Non è stato importato direttamente nel modulo Bambino meno che non si dica python a farlo, per esempio

from Parent import * 

vi darà accesso a tutti i membri del modulo controllante dall'interno del modulo Bambino

+1

Oppure utilizzare semplicemente un 'import sqlite3' sul modulo figlio. – jsbueno

+1

Perché mai accedere a sqlite3 tramite Parent? Inoltre, "import *" non è eccezionale. –

+1

D'accordo, questa è una cattiva risposta ad accettare - "import sqlite3'' è il modo corretto per farlo. –

5

Il bambino ha il proprio spazio dei nomi e non è stato importato sqlite3 dentro. Quindi è necessario importare sqlite3 in Child.py. Potresti anche fare import Parent.sqlite3 e quindi chiamare Parent.sqlite3.connect. Non c'è alcun reale vantaggio nel farlo in quel modo invece di importare solo sqlite3, dato che i moduli vengono importati solo una volta (alla prima importazione il codice raggiunge) e le importazioni seguenti aggiungono semplicemente il modulo allo spazio dei nomi corrente.

2

non hai importato il sqlite3 modulo nella classe Parent (si potrebbe, ma sarebbe davvero strano). Hai importato sqlite3 nel modulo Parent.py, che include la classe Parent e utilizza il modulo sqlite3 nella sua definizione.

Quindi un modulo separato importa il modulo Parent.py e definisce una sottoclasse di Parent. Ciò non porta automaticamente tutto nella classe Parent nell'ambito [1], e certamente non porta tutto ciò che era in ambito quando stavi definendo la classe Parent in Parent.py nell'ambito. Se hai dichiarato altre classi in Parent.py, non ti saresti aspettato che quei nomi fossero nello scope in Child solo perché erano nello stesso modulo della sua classe genitore, quindi perché dovresti aspettarti questo di un modulo che viene usato solo in definendo alcuni dei metodi di Parent?

Hai già un riferimento allo spazio dei nomi in cui è stato importato sqlite3; hai preso la classe Parent per creare una sottoclasse quando hai detto class Child(Parent.Parent). Quindi tu potresti usare Parent.sqlite3 per accedere a sqlite3, ma questo è un modo molto strano di usare i moduli in Python.

Normalmente è meglio aggiungere import sqlite3 all'inizio di Child.py. Quindi chiunque legga il codice vedrà che usa sqlite3.Se vedi che stai usando, ti chiederai perché non hai usato il modo normale e pensi che potresti fare qualcosa di complicato come avvolgere il modulo sqlite3 con un altro codice aggiunto. E se hai appena fatto import * from Parent, allora non è nemmeno ovvio lo da cui proviene il il nome sqlite3 ei tuoi lettori saranno davvero confusi. E il tuo codice smetterà misteriosamente di funzionare quando decidi di non aver bisogno di importarein Parent.py dopotutto, ma il messaggio di errore non ti dirà nulla su Parent.py.

In genere, se stai facendo cose ovvie come l'importazione di un modulo standard, dovresti farlo in modo semplice e ovvio. Le persone sono abituate a leggerlo e lo prenderanno molto facilmente senza bisogno di fermarsi a pensarci. Il "lettore confuso" che è più probabile che sia un problema è te stesso in pochi mesi in cui hai dimenticato esattamente come funzionava questo codice; vuoi renderlo il più semplice possibile per te stesso quando hai il compito di capirlo di nuovo.


[1] Ereditare da una classe genitore non ha nulla a che fare con portata, vale a dire ciò che i nomi si può accedere senza di loro qualificazione. Non si accede ai metodi e alle variabili di classe della classe genitore all'interno del blocco di classe che definisce la classe figlio. Ciò che significa è che dopo che la classe figlia è stata creata, il protocollo di risoluzione dei nomi per le variabili di istanza e classe si troveranno in Parent se non trovano le cose nella classe child. Questo è un punto un po 'sottile, che fondamentalmente si riduce a (1) all'interno del blocco classe figlio (comprese le definizioni dei metodi) some_parent_method() ti darà un errore, ma (2) dopo che la classe figlio esiste (incluso quando i metodi sono effettivamente eseguiti) Child.some_parent_method() (o self.some_parent_method() all'interno di un metodo) troverà il metodo del genitore.