Pregunta

locals está construido en una función que devuelve un diccionario de valores locales. La documentación dice:

  

Advertencia

     

El contenido de este diccionario debe   no ser modificado; cambios no pueden   afectar a los valores de las variables locales   utilizado por el intérprete.

Por desgracia, ejecutivo tiene el mismo problema en Python 3.0. ¿Hay alguna manera alrededor de esto?

Caso de Uso

Considere lo siguiente:

@depends("a", "b", "c", "d", "e", "f")
def test():
    put_into_locals(test.dependencies)

depende de las tiendas de las cadenas provistas en sus argumentos en un test.dependences lista. Estas cadenas son claves en un d diccionario. Me gustaría ser capaz de escribir put_into_locals para que pudiéramos tirar de los valores de d y ponerlas en los locales. ¿Es esto posible?

¿Fue útil?

Solución

Acabo de probar ejecutivo y funciona en Python 2.6.2

>>> def test():
...     exec "a = 5"
...     print a
...
>>> test()
5

Si está utilizando Python 3.x, que ya no funciona, porque los locales están optimizados como una matriz en tiempo de ejecución, en lugar de utilizar un diccionario.

Cuando Python detecta la "sentencia exec", que obligará a Python para cambiar el almacenamiento local de la matriz de diccionario. Sin embargo, ya que "exec" es una función en Python 3.x, el compilador no puede hacer esta distinción ya que el usuario podría haber hecho algo así como "exec = 123".

http://bugs.python.org/issue4831

  

Para modificar los locales de una función de   la marcha no es posible sin   varias consecuencias: normalmente,   locales de funciones no se almacenan en una   diccionario, pero una matriz, cuya   índices se determinan en tiempo de compilación   a partir de los lugares conocidos. esto choca   al menos con nuevos agregados por los locales   Exec. La vieja sentencia exec   eludido esto, debido a que la   compilador sabía que si un ejecutivo sin   globales / Locales args se produjeron en una   función, ese espacio de nombres sería   "No optimizado", es decir, no utilizando la   locales matriz. Desde exec () es ahora una   función normal, el compilador no lo hace   saben lo que "ejecutivo" puede estar unido a, y   por lo tanto, no puede tratar es especialmente.

Otros consejos

Las variables locales son modificados por las instrucciones de asignación.

Si tiene claves de diccionarios que son cadenas, por favor no también hacer que las variables locales -. Simplemente los utilizan como claves del diccionario

Si es absolutamente debe han variables locales hacer esto.

def aFunction( a, b, c, d, e, f ):
    # use a, b, c, d, e and f as local variables

aFunction( **someDictWithKeys_a_b_c_d_e_f )

que poblarán algunas variables locales de su diccionario sin hacer nada mágico.

Esto no es posible. Creo que esto es para permitir la optimización del rendimiento en el futuro. bytecode Python hace referencia a los locales por el índice, no por su nombre; Si se requirió locales () para tener permiso de escritura, podría evitar que los intérpretes de la implementación de algunas optimizaciones, o hacerlos más difícil.

Estoy bastante seguro de que no vas a encontrar ninguna API central que garantiza que puede editar los locales de este tipo, porque si esa API podía hacerlo, locals () no tendrían esta restricción tampoco.

No se olvide que todos los locales deben existir en tiempo de compilación; si hace referencia a un nombre que no está unido a un local en tiempo de compilación, el compilador asume que es un mundial. No se puede "crear" locales después de la compilación.

Consulte esta pregunta para una posible solución, pero es un corte serio y que realmente no quiere hacer eso.

Tenga en cuenta que hay un problema básico con el código de ejemplo:

@depends("a", "b", "c", "d", "e", "f")
def test():
    put_into_locals(test.dependencies)

"test.dependencies" no se refiere a "f.dependencies" donde F es la función actual; se hace referencia al valor mundial real "prueba". Esto significa que si se utiliza más de un decorador:

@memoize
@depends("a", "b", "c", "d", "e", "f")
def test():
    put_into_locals(test.dependencies)

Se va a trabajar ya no, ya que "prueba" es memoize su función envuelto, no depende de. Python realmente necesita una forma de referirse a "la función que se está ejecutando-" (y clase).

Me almacenarlo en una variable:

refs    = locals()
def set_pets():
    global refs
    animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
    for i in range(len(animals)):
        refs['pet_0%s' % i] = animals[i]

set_pets()
refs['pet_05']='bird'
print(pet_00, pet_02, pet_04, pet_01, pet_03, pet_05 )
>> dog fish monkey cat fox bird

Y si desea probar su dict antes de meterla en los locales ():

def set_pets():
    global refs
    sandbox = {}
    animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
    for i in range(len(animals)):
        sandbox['pet_0%s' % i] = animals[i]
    # Test sandboxed dict here
    refs.update( sandbox )

Python 3.6.1 en MacOS Sierra

No estoy seguro de si está sujeto a las mismas restricciones, pero se puede obtener una referencia directa a la trama actual (y de ahí, las variables locales del diccionario) a través del módulo de inspección:

>>> import inspect
>>> inspect.currentframe().f_locals['foo'] = 'bar'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'foo', 'inspect']
>>> foo
'bar'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top