2010-06-23 8 views
6

Estoy lidiando con algún código de Python generado automáticamente para mí. Quiero evitar editar manualmente estos archivos pitón & por lo tanto, esta pregunta/tema:Ámbito de "importación" de Python

foo.py:

def foo(): 
    print "foo" 

boo.py:

def boo(): 
    foo.foo() # <-- global name 'foo' not defined 
    print "boo" 

bar.py:

import foo 
import boo 
def bar(): 
    boo.boo() 
    print "bar" 

Ejecución de:

python.exe bar.py

da un error que Boo No se encontró foo. Pero la barra está importando ambos foo & boo. ¿No debería estar disponible automáticamente para abuchear?

¿Hay alguna manera de hacerlo? Como dicho boo.py se genera automáticamente para mí & Quiero evitar agregar importación foo a boo.py

Gracias.

Respuesta

14

Pero barra está importando tanto foo & Boo. ¿No debería ser foo ser automáticamente disponible para abuchear?

No, no debe: import, como cualquier otra forma de enlazar un nombre, ese nombre se une en un solo ámbito, específica, no "en todos los ámbitos que jamás podría desear en".

¿Hay alguna manera de hacerlo? Como dijo boo.py se genera automáticamente para me & Quiero evitar la adición de foo importación a boo.py

Hay un truco muy mal - no me gustaría vivir con ella (I' Más bien derrocharé mi energía en obtener ese generador de código totalmente descompuesto que hace que boo.py se solucione, si tiene un error tan grande como la falta de una importación necesaria, ¿qué otros horrores puede tener almacenados ?!), pero, oye, no es mi funeral ... ;-)

Tener bar.py inicio ...:

import foo 
import boo 
import __builtin__ 
__builtin__.foo = foo 

De esta manera se ha hecho identificador foo un "falso, artificial incorporada nombre" (el único tipo de nombre que es disponible en todos los ámbitos, a menos que la sombra de otros enlaces intermedios del nombre en alcances más cercanos) refiriéndose al módulo foo.

NO procedimiento recomendado, solo una solución temporal para el error horrible y evidente en el generador de código que genera boo.py. ¡Arregla ese error para que puedas retirar este truco lo antes posible!

+0

OK. Pediré a los muchachos que agreguen manualmente "import foo" a todos estos archivos py. Y arreglaré esta herramienta de generación .py más tarde. Gracias. – sambha

+1

@AlexMartelli Me encontré con este truco y para mis propósitos es lo suficientemente bueno. Pero todavía estoy desconcertado sobre todas las implicaciones de poner nombres en el '__builtin__'. Además del problema obvio con las colisiones de nombres, ¿hay algunas otras dificultades notables? – LavaScornedOven

3

No. Si quiere que foo esté disponible en boo, necesita importarlo en boo. El import foo que está en bar solo hace que foo esté disponible en el módulo bar.

En general, una declaración import en Python es algo así como una definición variable. En realidad se podría pensar en él de esa manera: mentalmente sustituir

import boo 

con

boo = __import__('boo') 

(__import__ es una función interna del intérprete de Python que sea importa un módulo, o mira hacia arriba una referencia a la existente módulo si ya se importó y devuelve esa referencia)

Lo que se está generando automáticamente boo.py lo está haciendo mal. Debería estar agregando import foo en algún lugar dentro de ese archivo. Se puede conseguir alrededor de él al hacer esto en bar.py:

import foo 
import boo 
boo.foo = foo 

pero que realmente no debería tener que estar haciendo eso. (Me hago eco de lo dicho Alex Martelli sobre este tipo de cosas es un gran truco)

+0

OK. Gracias. Esperaré un poco más de tiempo para que otros hagan sonar la voz. Si alguien tiene algún truco. De lo contrario, tengo que hacer lo que tengo que hacer. – sambha

+0

K. Agregaremos import foo manualmente a estos archivos py por ahora y reparará la herramienta más adelante. A veces odio este "rigor" de la pitón, pero con el tiempo lo entiendo: generalmente es el "camino correcto". Gracias. – sambha

4

que tiene que importar foo en Boo

boo.py

import foo 

def boo(): 
    foo.foo() # <-- global name 'foo' not defined 
    print "boo" 

bar.py

import boo 

def bar(): 
    boo.boo() 
    print "bar" 
+1

Las importaciones circulares indican un error de diseño. –

+0

y hay un problema para resolver problemas cuando el código es demasiado apretado acoplado ... la refactorización es la única solución;) es por eso que me encanta Python :) –

+1

@MikeGraham No veo una importación circular aquí ... – drevicko

4

Cada módulo tiene su propio espacio de nombres. Entonces, para que boo.py vea algo de un módulo externo, boo.py debe importarlo.

Es posible escribir un idioma en el que los espacios de nombres se apilan de la manera que usted espera: esto se denomina ámbito dinámico. Algunos lenguajes como el lisp original, las primeras versiones de Perl, PostScript, etc. usan (o admiten) el alcance dinámico.

La mayoría de los idiomas utilizan el ámbito léxico. Resulta que esta es una forma mucho más agradable para que los idiomas funcionen: de esta forma, un módulo puede razonar sobre cómo funcionará en función de su propio código sin tener que preocuparse por cómo se lo llamó.

Consulte este artículo para obtener detalles adicionales: http://en.wikipedia.org/wiki/Scope_%28programming%29

Cuestiones relacionadas