2012-07-19 12 views
7

Supongamos que tengo una jerarquía de funciones, quiero poder acceder (¡no cambiar!) el alcance de los padres. Aquí hay un ejemplo ilustrativo.Leyendo el alcance de un padre en python

def f(): 
    a = 2 
    b = 1 
    def g(): 
     b = 2 
     c = 1 
     print globals() #contains a=1 and d=4 
     print locals() #contains b=2 and c=1, but no a 
     print dict(globals(), **locals()) #contains a=1, d=4 (from the globals), b=2 and c=1 (from g) 
     # I want a=2 and b=1 (from f), d=4 (from globals) and no c 
    g() 
a = 1 
d = 4 
f() 

¿Puedo acceder a f 's alcance desde dentro g?

+0

Tiene un código de ejemplo allí. Podrías probarlo. –

+0

Creo que esto sería interesante para ti: http://ynniv.com/blog/2007/08/closures-in-python.html – fuaaark

+0

@arxanas El código de ejemplo que tengo no lo hace, sin embargo ilustra el problema, consulte la línea 10. –

Respuesta

5

En general, no se puede en Python. Si su implementación Python admite marcos de pila (CPython sí), puede inspeccionar el marco de la función de llamada utilizando el módulo inspect y extraer las variables locales, pero dudo que esta sea la mejor solución para el problema que desea resolver (cualquiera que sea). . Probablemente haya algún defecto en su diseño si cree que lo necesita.

Tenga en cuenta que usar inspect le permitirá subir a la pila de llamadas , no en la pila de ámbitos léxicos. Si devuelve g desde f(), el alcance de f desaparecerá, por lo que no hay forma de acceder a él, ya que ni siquiera existe.

+0

¿Son razones de seguridad por no poder hacer esto? Encuentro el alcance tan sutil/confuso, pero el alcance de 'f' seguramente todavía" existe "una vez que se llama' g' dentro de 'f', ya que luego se vuelve a ejecutar' f' (!) La razón por la que estaba pensando en esto es para [prueba unitaria de efectos secundarios] (http://stackoverflow.com/questions/11559401/testing-for-side-effects-in-python#comment15290923_11559401) ...: s –

+5

@hayden: No, no es por razones de seguridad. Como dije, * puedes * subir la pila de llamadas si tu implementación de Python admite marcos de pila; simplemente haz algo como 'inspect.currentframe(). F_back.f_locals' para obtener los locales del marco de llamada, que será una instancia de 'f' en tu ejemplo. La razón por la que no puede acceder a las variables desde un alcance * lexical * es que esta noción no tiene sentido. Puede haber varias instancias de 'f' en la pila de llamadas, todas con diferentes locales, o no podría haber ninguna. –

+1

La razón por la que * no debería * estar haciendo algo como esto va en contra de la esencia de un lenguaje de programación con alcance léxico como lo es el alcance dinámico (es decir, prácticamente cualquier lenguaje de programación). Consulte http://en.wikipedia.org/wiki/Dynamic_scoping#Lexical_scoping_and_dynamic_scoping para obtener más detalles. –

Cuestiones relacionadas