2010-03-06 9 views
10

Acabo de leer un artículo que supuestamente me introdujo en un nuevo concepto: Hasta ahora estaba seguro de que los paquetes de python (es decir, directorios con un archivo __init__.py) se comportan exactamente igual que los paquetes de Java, es decir, pequeños espacios de nombres para ayudar arregle el código (menos el alcance del "paquete" de java). Pero, de acuerdo con este enlace: A Short Digression Into Multi-File Modules, si pongo todos mis archivos en el mismo "paquete":¿Los paquetes python (módulos multi-archivo) se comportan exactamente como un gran módulo?

toda la colección de archivos se presenta a otro código Python como un único módulo - como si todo el las funciones y las clases estaban en un solo .py

Así que ahora pensé que todo mi entendimiento del "paquete" python era incorrecto. Además, no es un paquete, sino un "módulo multifilar", como se lo refiere el autor.

Entonces, por lo que entendí, no importa la cantidad de archivos que divido mis funcs y clases dentro de un paquete, desde afuera ese paquete debería aparecer como si tomara todo el código de todos los archivos dentro del paquete y lo pusiera en un gran archivo con el mismo nombre del paquete, es decir, como un solo módulo.

por ejemplo, si tengo la siguiente estructura de archivos:

/base 
    /animals 
     /__init__.py 
     /dog.py 

y en dog.py:

def bark(): 
    print "woof" 

que debería ser exactamente el mismo que tener:

/base 
    /animals.py 

y en animals.py:

def bark(): 
    print 'woof' 

por lo tanto, esta nueva pieza de código debería funcionar bien en ambos casos:

from base import animals 
animals.bark() 

Este curso de los rendimientos en el primer caso:

Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
AttributeError: 'module' object has no attribute 'bark' 

Qué me estoy perdiendo aquí? Veo, con la excepción de que "animals", de hecho, se trata como un módulo, pero parece que todavía tengo que declarar explícitamente animals.dog.bark, es decir, que la estructura de archivos internos del paquete no se abstrae del exterior.

¿Me falta el punto del autor, o simplemente no lo estoy implementando correctamente?

=== === EDITAR

Sólo para asegurarse de que nadie pierde esta línea en la cita:

como si todas las funciones y clases estaban en una soltero .py

independientemente de cómo acceder a la realidad esta funcs y clases, la cita anterior establece explícitamente que si usted tiene un func1 en el archivo A y func2 en el archivo B, independientemente de qué camino van a ser accesibles desde, si denote esta ruta como X, entonces, de acuerdo con la cita mencionada, tanto X.func1 como X.func2 deberían funcionar.

+0

No he podido encontrar esa cita en la página vinculada. ¿Te importa intentarlo de nuevo? –

+0

@Ignacio: http://diveintopython3.org/case-study-porting-chardet-to-python-3.html#multifile-modules – unutbu

+0

@ignacio - perdon, corrigió el enlace – olamundo

Respuesta

4

El autor ha simplificado demasiado las cosas. Él dice que todo lo que se encuentra bajo animal se puede ver como si estuviera en el mismo módulo, aunque el hecho es que los nombres en animal.dog estarán en su propio espacio de nombres.

+0

OK, bien. Pensé que me estaba perdiendo algo :) – olamundo

4

Quizás el punto es simplemente que un paquete es solo un tipo específico de módulo.

/base 
    /animals 
     /__init__.py 
     /dog.py 

Sólo significa que cualquier cosa que se define en o importación en __init__.py será visible en el interior del módulo de animals.

Así animals es un módulo (que es un paquete) y animals.dog es un módulo que es un submódulo de animals, pero no un paquete.

También significa que si tiene un módulo simple animals puede sustituirlo por un paquete con el mismo nombre en la próxima versión y organizarlo para que los usuarios no noten la diferencia.

Si desea que todas las clases de submódulos del paquete conforman un módulo visible para el usuario individual (espacio de nombres), usted tiene que definir una línea como la siguiente para cada submódulo, en __init__.py:

from animals.dog import * 
+0

, por favor vea la edición que agregué a mi pregunta - Creo que muestra claramente que esta respuesta pasa por alto el punto del autor (a menos que también me falta algo en tu respuesta :)) – olamundo

+0

el texto al que enlazas es ciertamente incorrecto y fácil de malinterpretar. pero mi respuesta es simplemente lo que creo que es una respuesta sensata a una pregunta estrechamente relacionada, y también muestra cómo puedes hacerlo realidad: cómo puedes hacer que parezca que todas las funciones y clases están definidas en el mismo archivo .py . El texto vinculado implica que esto es automático, pero no lo es, es una mera posibilidad. – u0b34a0f6ae

+0

Sin embargo, en un nivel superior, lo que está escrito * es * verdadero, ya que un paquete reúne el contenido de todos los archivos .py que desee detrás de un único nombre de módulo de nivel superior. Sin embargo, no recoge todos los atributos de forma inmediata en el espacio de nombres del módulo. – u0b34a0f6ae

0

que pueda Realmente lo explicas bien, pero tal vez el siguiente código ayude. Si dejo su primera estructura de archivos como es, y en lugar de modificar el segundo a tener la siguiente en el archivo animals.py:

class Dog: 
    def bark(self): pass 
dog=Dog() 

Luego, en ambos casos,

from base import animals 
animals.dog.bark() 

va a funcionar.

+0

bueno, sí, en ese caso específico ambos funcionarán. Pero el reclamo del autor es mucho más sólido que eso: los módulos se comportan como un gran módulo. Lo que ha demostrado es que los módulos en un paquete se comportan como un gran módulo con propiedades, algo que creo que la mayoría de la gente sabe :) Cita del autor: "como si todas las * funciones * y * clases * estaban en un solo .py "- esto significa explícitamente que animals.bark debería ser suficiente. – olamundo

1

No es una respuesta real, pero como aún no estoy autorizado a comentar (suspiro!):

Desde diveintopython es muy usado/citado recurso/referencia para los programadores de Python (al menos cuando empiezan a), deberías contactar al autor sobre este defecto, ya que también será engañoso para otros. Hay alguna información de contacto en la página de inicio de diveintopython3 y también puede presentarla como un problema en github.

Cuestiones relacionadas