¿Dónde está nonlocals ()?

¿Cómo obtengo las variables no locales para el scope actual? Las funciones vars , locals y globals existen, pero ¿existe una función para obtener los nonlocals ?

¿Por qué no se enumeran los no locales cuando se llama vars ?

Actualizar

Mi problema es que no hay manera de enumerar las variables disponibles en el scope actual, ya que ni vars ni globals incluyen a AFAICT no locales.

Con frecuencia uso vars en códigos como los siguientes:

 '{meh[0]}/{meh[3]} {a}{b}{c}'.format(**vars()) 

Lo cual falla si alguna de estas variables está en el scope de una función contenedora.

Desde el código en ejecución, puede obtener fácilmente los nombres de las variables no locales, pero recuperar su contenido de una manera en que una llamada a los locals hace que un diccionario sea un poco más complicado.

Los nombres de variables nonlocal utilizados se almacenan en el objeto de código en ejecución actual, en el atributo co_freevars.

Por lo tanto, obtener los nombres no locales es una cuestión de:

names = inspect.currentframe().f_code.co_freevars

Sin embargo, el contenido de estas variables se almacena en el atributo func_closure ( func_closure , en Python 2), del objeto de función . (No es el objeto de código). El problema es que, sin la “ayuda externa”, no hay una manera fácil para que un código en ejecución llegue al objeto de función en el que se está ejecutando. Puede acceder al objeto de marco, que enlaza con el objeto de código, pero no hay enlaces al objeto de función. (Para una función definida de nivel superior se podría usar explícitamente el nombre conocido de la función, tal como se usa en la statement de def , pero para una función encerrada, que se devuelve a la persona que llama, tampoco hay forma de saber su nombre).

Por lo tanto, uno tiene que recurrir a un truco: obtener todos los objetos que se vinculan al objeto de código actual, utilizando el módulo gc (recolector de basura). Hay una llamada a gc.get_referrers todos los objetos de función que enlazan. El objeto de código uno tiene.

Entonces, dentro de una función con variables no_local se podría hacer:

 import inspect, gc def a(b): b1 = 2 def c(): nonlocal b1 print (b) code = inspect.currentframe().f_code names = code.co_freevars function = [func for func in gc.get_referrers(code) if isinstance(func, FunctionType)][0] nonlocals = dict (zip(names, (x.cell_contents for x in function.__closure__ ))) print(nonlocals) return inspect.currentframe() return c c = a(5) f = c() 

Y por lo tanto recuperar los nombres y valores de los no locales. Pero esto no funcionará si tiene más de una instancia de esa función alrededor (es decir, si la función de interesado se creó más de una vez con más de una llamada a la función que la genera): debido a que todas esas instancias enlace al mismo objeto de código. El ejemplo anterior, asume que solo hay una función ejecutándose con el código actual, y funcionaría correctamente en este caso. Otra llamada a la función de facción crearía otra función, con potencialmente otros valores para las variables no locales, pero con el mismo objeto de código: la function = list genrator anterior recuperaría todas esas, y seleccionaría arbitrariamente la primera de ellas.

La función “correcta” es aquella en la que se está ejecutando el código actual. Estoy tratando de pensar en una forma de recuperar esta información, pero no puedo acceder a ella. Si puedo, completaré esta respuesta, pero por ahora, esto no puede ayudarlo a recuperar los valores de los valores no locales.

(acabo de descubrir que tratar de usar “eval” con un nombre de variable no local tampoco funcionará)

Parece que lo único que vincula el marco de ejecución actual con el objeto de función donde se mantienen los valores de las variables no locales se crea en el tiempo de ejecución dentro del lado nativo del intérprete de Python. No puedo pensar en una manera de no llegar a utilizar el módulo ctypes para ver las estructuras de datos de los intérpretes en tiempo de ejecución, lo que, por supuesto, no sería adecuado para ningún código de producción real.

La línea de fondo: puede recuperar de manera confiable los nombres de las variables no locales. Pero parece que no puede obtener su valor dado su nombre como una cadena (no volver a enlazar en ese momento).

Puede intentar abrir una solicitud de función para una llamada “no localizada” en el rastreador de errores de Python o en la lista de correo de Python-ideas.