2012-01-22 17 views
7

Tengo un error de importación gracioso cuando uso Inheritence en Python.Python Child no puede usar un Módulo Parent Imported

En una clase padre, importo el módulo sqlite3, en una clase secundaria trato de usar una función sqlite3 pero obtengo un error que dice "NameError: nombre global 'sqlite3' no está definido". ¿Por qué sucede esto? & ¿cómo lo arreglo?

Las 2 clases son en archivos separados:

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() 

Respuesta

12

el módulo del sqlite3 se importa en el módulo de Padres de ahí que necesita para acceder a él a través de ese módulo

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

No se importa directamente en el módulo del niño a menos que se diga pitón de hacerlo, por ejemplo

from Parent import * 

le dará acceso a todos los miembros del módulo de Padres desde el módulo niño

+1

O simplemente use 'import sqlite3' en el módulo secundario también. – jsbueno

+1

¿Por qué diablos accederá a sqlite3 a través de Parent? Además, "importar *" no es genial. –

+1

De acuerdo, esta es una mala respuesta para aceptar - '' import sqlite3'' es la forma correcta de hacerlo. –

5

El niño tiene su propio espacio de nombres y no se ha importado sqlite3 en ello. Por lo tanto, debe importar sqlite3 a Child.py. También puede hacer import Parent.sqlite3 y luego llamar al Parent.sqlite3.connect. No hay una ventaja real de hacerlo así en lugar de simplemente importar sqlite3, ya que los módulos solo se importan una vez (en la primera importación que alcanza el código) y las siguientes importaciones solo agregan el módulo al espacio de nombres actual.

2

no ha importado el sqlite3 módulo en la clase Parent (podrías, pero eso sería realmente extraño). Ha importado sqlite3 en el Parent.pymódulo, que incluye la clase Parent, y utiliza el módulo sqlite3 en su definición.

Luego, un módulo independiente importa el módulo Parent.py y define una subclase de Parent. Esto no lleva automáticamente todo en la clase Parent al alcance [1], y ciertamente no incluye todo lo que estaba en el alcance cuando definía la clase Parent en Parent.py en el alcance. Si declaró otras clases en Parent.py, no esperaría que esos nombres estuvieran en el alcance en Child solo porque estaban en el mismo módulo que su clase principal, entonces ¿por qué esperaría esto de un módulo que simplemente se utiliza en definir algunos de los métodos de Parent?

Ya tiene una referencia al espacio de nombre donde se importó sqlite3; obtuviste la clase Parent para subclase cuando dijiste class Child(Parent.Parent). De modo que podría usar Parent.sqlite3 para acceder al sqlite3, pero esa es una forma muy extraña de usar módulos en Python.

Normalmente es mejor agregar import sqlite3 a la parte superior de Child.py. Entonces, cualquiera que lea el código verá que usa sqlite3.Si lo ve usando sqlite3 que ha importado de Parent.py, se preguntará por qué no lo usó de la manera normal, y piensa que podría estar haciendo algo complicado como envolver el módulo sqlite3 con algún código adicional que haya agregado. Y si acabas de hacer import * from Parent, entonces ni siquiera es obvio donde se originó el nombre sqlite3, y tus lectores realmente estarán confundidos. Y su código misteriosamente dejará de funcionar cuando usted decida que no necesita importar sqlite3 en Parent.py después de todo, pero el mensaje de error no le dirá nada sobre Parent.py.

En general, si está haciendo cosas obvias simples como importar un módulo estándar, debe hacerlo de la manera simple y obvia. La gente está acostumbrada a leer eso, y lo asimilará fácilmente sin necesidad de detenerse a pensarlo. El "lector confundido" que probablemente sea un problema es usted mismo en unos pocos meses cuando olvidó exactamente cómo funcionaba este código; desea hacer que sea lo más fácil posible para usted cuando consigue el trabajo de resolverlo de nuevo.


[1] La herencia de una clase padre no tiene nada que ver con alcance, es decir, qué nombres se puede acceder a ellas sin calificar. No tiene acceso a los métodos y variables de clase de la clase principal dentro del bloque de clase que define la clase secundaria. Lo que significa es que después de que se crea la clase hija, el protocolo de resolución de nombres para la instancia y las variables de clase buscarán en el elemento primario si no encuentran elementos en la clase hija. Este es un punto un tanto sutil, que básicamente se reduce a (1) dentro del bloque de clases hijo (incluidas las definiciones de métodos) some_parent_method() le dará un error, pero (2) después de que existe la clase hija (incluso cuando los métodos se ejecutan realmente) Child.some_parent_method() (o self.some_parent_method() dentro de un método) encontrará el método de los padres.

Cuestiones relacionadas