name - python create variables automatically
Establece dinĂ¡micamente la variable local (7)
Esta pregunta ya tiene una respuesta aquí:
¿Cómo se establece dinámicamente la variable local en Python?
(donde el nombre de la variable es dinámico)
ACTUALIZACIÓN: soy consciente de que esta no es una buena práctica, y las observaciones son legítimas, pero esto no la convierte en una pregunta mala, sino más bien teórica: no veo por qué esto justifica los votos a la baja.
(Solo una nota rápida para otros googlin '')
Ok, entonces modificando locals()
no es el camino a seguir (mientras se supone que la modificación de globals()
funciona ). Mientras tanto, exec
podría serlo , pero es dolorosamente lento, así que, al igual que con las expresiones regulares, podemos compile()
primero:
# var0 = 0; var1 = 1; var2 = 2
code_text = ''/n''.join( "var%d = %d" % (n, n) for n in xrange(3) )
filename = ''''
code_chunk = compile( code_text, filename, ''exec'' )
# now later we can use exec:
exec code_chunk # executes in the current context
A diferencia de otras respuestas ya publicadas, no se puede modificar locals()
directamente y esperar que funcione.
>>> def foo():
lcl = locals()
lcl[''xyz''] = 42
print(xyz)
>>> foo()
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
foo()
File "<pyshell#5>", line 4, in foo
print(xyz)
NameError: global name ''xyz'' is not defined
La modificación de locals()
no está definida. Fuera de una función cuando locals()
y globals()
son lo mismo, funcionará; dentro de una función generalmente no funcionará.
Use un diccionario o establezca un atributo en un objeto:
d = {}
d[''xyz''] = 42
print(d[''xyz''])
o si lo prefiere, use una clase:
class C: pass
obj = C()
setattr(obj, ''xyz'', 42)
print(obj.xyz)
Editar : El acceso a las variables en espacios de nombres que no son funciones (módulos, definiciones de clase, instancias) generalmente se realizan mediante búsquedas de diccionario (como señala Sven en los comentarios, hay excepciones, por ejemplo, clases que definen __slots__
). Los locales de la función se pueden optimizar para la velocidad porque el compilador (por lo general) conoce todos los nombres por adelantado, por lo que no hay un diccionario hasta que no llame a locals()
.
En la implementación C de Python locals()
(llamado desde dentro de una función) crea un diccionario ordinario inicializado a partir de los valores actuales de las variables locales. Dentro de cada función, cualquier número de llamadas a los locals()
devolverá el mismo diccionario, pero cada llamada a los locals()
lo actualizará con los valores actuales de las variables locales. Esto puede dar la impresión de que se ignora la asignación a elementos del diccionario (originalmente escribí que este era el caso). Las modificaciones a las claves existentes dentro del diccionario devueltas desde locals()
solo duran hasta la próxima llamada a locals()
en el mismo ámbito.
En IronPython las cosas funcionan de manera diferente. Cualquier función que llame a locals()
dentro de ella usa un diccionario para sus variables locales, por lo que las asignaciones a las variables locales cambian el diccionario y las asignaciones al diccionario cambian las variables PERO eso solo es así si explícitamente llama a locals()
bajo ese nombre. Si enlaza un nombre diferente a la función locals
en IronPython, al llamarlo obtendrá las variables locales para el alcance al que estaba vinculado el nombre y no hay forma de acceder a la función local a través de él:
>>> def foo():
... abc = 123
... lcl = zzz()
... lcl[''abc''] = 456
... deF = 789
... print(abc)
... print(zzz())
... print(lcl)
...
>>> zzz =locals
>>> foo()
123
{''__doc__'': None, ''__builtins__'': <module ''__builtin__'' (built-in)>, ''zzz'': <built-in function locals>, ''foo'': <function foo at 0x000000000000002B>, ''__name__'': ''__main__'', ''abc'': 456}
{''__doc__'': None, ''__builtins__'': <module ''__builtin__'' (built-in)>, ''zzz'': <built-in function locals>, ''foo'': <function foo at 0x000000000000002B>, ''__name__'': ''__main__'', ''abc'': 456}
>>>
Todo esto podría cambiar en cualquier momento. Lo único garantizado es que no puede depender de los resultados de la asignación al diccionario devuelto por los locals()
.
Digamos que tenemos el siguiente diccionario:
DictionaryA = {''No Rating'': [''Hobbit'', ''Movie C'', ''Movie G''],
''Forget It'': [''Avenger'', ''Movie B''],
''Must See'': [''Children of Men'', ''Skyfall'', ''Movie F''],
''3'': [''X-Men'', ''Movie D''],
''2'': [''Captain America'', ''Movie E''],
''4'': [''Transformers'', ''Movie A'']}
Quiero crear nuevos diccionarios de la siguiente manera:
NewDictionary1 = {''No Rating'': [''Hobbit'', ''Movie C'', ''Movie G'']}
NewDictionary2 = {''Forget It'': [''Avenger'', ''Movie B'']}
NewDictionary3 = {''Must See'': [''Children of Men'', ''Skyfall'', ''Movie F'']}
un oneliner:
dics = [{k:v} for k,v in DictionaryA.iteritems()]
sería enviado a:
[{''Must See'': [''Children of Men'', ''Skyfall'', ''Movie F'']}, {''Forget It'': [''Avenger'', ''Movie B'']}, {''No Rating'': [''Hobbit'', ''Movie C'', ''Movie G'']}, {''3'': [''X-Men'', ''Movie D'']}, {''2'': [''Captain America'', ''Movie E'']}, {''4'': [''Transformers'', ''Movie A'']}]
Pero para declarar con precisión las variables, podríamos ir con:
>>> i=0
>>> lcl = locals()
>>> for key,val in DictionaryA.iteritems():
lcl["Dict" + str(i)] = {key:val}
i += 1
Como se puede ver las primeras 3 variables Dict
:
>>> Dict0
{''Must See'': [''Children of Men'', ''Skyfall'', ''Movie F'']}
>>> Dict1
{''Forget It'': [''Avenger'', ''Movie B'']}
>>> Dict2
{''No Rating'': [''Hobbit'', ''Movie C'', ''Movie G'']}
Como lo mencionaron otros, si desea ponerlo en una función, debe agregarlo a los globals()
:
>>> glb = globals()
>>> for key,val in DictionaryA.iteritems():
glb["Dict" + str(i)] = {key:val}
i += 1
Me he pasado las últimas ... un par de horas, supongo, tratando de hackear la falta de cierres de funciones, y se me ocurrió esto, lo que podría ayudar:
common_data = ...stuff...
def process(record):
...logic...
def op():
for fing in op.func_dict: # Key line number 1
exec(fing + " = op.func_dict[fing]") # Key line number 2
while common_data.still_recieving:
with common_data._lock:
if common_data.record_available:
process(common_data.oldest_record)
time.sleep(1.0)
op.func_dict.update(locals()) # Key line number 3
threading.Thread(target = op).start()
...
Es un ejemplo bastante pesado / artificial, pero si hay muchos locales o si todavía estás en el proceso de creación de prototipos, este patrón se vuelve útil. En general, estaba resentido con respecto a todas las tiendas de datos que se replicaban o movían para manejar delegados de devolución de llamadas, etc.
Otros han sugerido asignar a los locals()
. Esto no funcionará dentro de una función, donde se accede a los locales utilizando el LOAD_FAST
operación LOAD_FAST
, a menos que tenga una declaración exec
en algún lugar de la función. Para admitir esta afirmación, que podría crear nuevas variables que no se conocen en tiempo de compilación, Python se ve obligado a acceder a variables locales por nombre dentro de la función, por lo que escribir en locals()
funciona. El exec
puede estar fuera de la ruta del código que se ejecuta.
def func(varname):
locals()[varname] = 42
return answer # only works if we passed in "answer" for varname
exec "" # never executed
func("answer")
>>> 42
Nota: Esto solo funciona en Python 2.x. Ellos eliminaron esta tontería en Python 3, y otras implementaciones (Jython, IronPython, etc.) pueden no ser compatibles.
Esta es una mala idea, sin embargo. ¿Cómo accederá a las variables si no conoce su nombre? Por locals()[xxx]
probablemente. Entonces, ¿por qué no usar su propio diccionario en lugar de contaminar a los locals()
(y arriesgarse a sobrescribir una variable que realmente necesita su función)?
Puede usar un diccionario local y colocar todas las vinculaciones dinámicas como elementos en el diccionario. Luego, conociendo el nombre de dicha "variable dinámica", puede usar el nombre como la clave para obtener su valor.
Puede modificar locals()
directamente:
locals()[''foo''] = ''bar''
Pero una mejor manera sería tener algún dict que contenga todos los nombres de variables dinámicas como claves del diccionario:
d = {}
for some in thing:
d[some] = ''whatever''