tipos - types of variables in python
¿Cómo creo un número variable de variables? (13)
Cualquier conjunto de variables también se puede envolver en una clase. Las variables "variables" pueden agregarse a la instancia de clase durante el tiempo de ejecución accediendo directamente al diccionario incorporado a través del atributo __dict__.
El siguiente código define la clase Variables, que agrega variables (en este caso atributos) a su instancia durante la construcción. Los nombres de las variables se toman de una lista específica (que, por ejemplo, podría haber sido generada por el código del programa):
# some list of variable names
L = [''a'', ''b'', ''c'']
class Variables:
def __init__(self, L):
for item in L:
self.__dict__[item] = 100
v = Variables(L)
print(v.a, v.b, v.c)
#will produce 100 100 100
¿Cómo logro variables variables en Python?
Aquí hay una entrada manual elaborativa, por ejemplo: Variables variables
He oído que esto es una mala idea en general, y es un agujero de seguridad en Python. ¿Es eso cierto?
El consenso es utilizar un diccionario para esto, vea las otras respuestas. Esta es una buena idea para la mayoría de los casos, sin embargo, hay muchos aspectos que surgen de esto:
- Usted mismo será responsable de este diccionario, incluida la recolección de basura (de variables in-dict), etc.
- no hay localidad o globalidad para las variables variables, depende de la globalidad del diccionario
- Si desea cambiar el nombre de una variable, deberá hacerlo manualmente.
- Sin embargo, usted es mucho más flexible, por ejemplo,
- Puedes decidir sobrescribir las variables existentes o ...
- ... elegir implementar variables const.
- plantear una excepción en la sobrescritura para diferentes tipos
- etc.
Dicho esto, he implementado una variable de administrador de variables que proporciona algunas de las ideas anteriores. Funciona para python 2 y 3.
Usarías la clase así:
from variableVariablesManager import VariableVariablesManager
myVars = VariableVariablesManager()
myVars[''test''] = 25
print(myVars[''test''])
# define a const variable
myVars.defineConstVariable(''myconst'', 13)
try:
myVars[''myconst''] = 14 # <- this raises an error, since ''myconst'' must not be changed
print("not allowed")
except AttributeError as e:
pass
# rename a variable
myVars.renameVariable(''myconst'', ''myconstOther'')
# preserve locality
def testLocalVar():
myVars = VariableVariablesManager()
myVars[''test''] = 13
print("inside function myVars[''test'']:", myVars[''test''])
testLocalVar()
print("outside function myVars[''test'']:", myVars[''test''])
# define a global variable
myVars.defineGlobalVariable(''globalVar'', 12)
def testGlobalVar():
myVars = VariableVariablesManager()
print("inside function myVars[''globalVar'']:", myVars[''globalVar''])
myVars[''globalVar''] = 13
print("inside function myVars[''globalVar''] (having been changed):", myVars[''globalVar''])
testGlobalVar()
print("outside function myVars[''globalVar'']:", myVars[''globalVar''])
Si desea permitir la sobrescritura de variables con el mismo tipo solamente:
myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars[''test''] = 25
myVars[''test''] = "Cat" # <- raises Exception (different type on overwriting)
En lugar de un diccionario, también puede utilizar nameduuple desde el módulo de colecciones, lo que facilita el acceso.
por ejemplo:
#using dictionary
variables = {}
variables["first"] = 34
variables["second"] = 45
print variables["first"], variables["second"]
#using namedtuple
Variables = namedtuple(''Variables'', [''first'', ''second''])
vars = Variables(34, 45)
print vars.first, vars.second
Estoy respondiendo la pregunta: ¿Cómo obtener el valor de una variable dado su nombre en una cadena? que está cerrado como un duplicado con un enlace a esta pregunta.
Si las variables en cuestión son parte de un objeto (parte de una clase, por ejemplo), entonces algunas funciones útiles para lograr exactamente eso son hasattr
, getattr
y setattr
.
Así, por ejemplo, puedes tener:
class Variables(object):
def __init__(self):
self.foo = "initial_variable"
def create_new_var(self,name,value):
setattr(self,name,value)
def get_var(self,name):
if hasattr(self,name):
return getattr(self,name)
else:
raise("Class does not have a variable named: "+name)
Entonces puedes hacer:
v = Variables()
v.get_var("foo")
"initial_variable"
v.create_new_var(v.foo,"is actually not initial")
v.initial_variable
"en realidad no es inicial"
La clase SimpleNamespace
podría usarse para crear nuevos atributos con setattr
, o la subclase SimpleNamespace
y crear su propia función para agregar nuevos nombres de atributos (variables).
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**v)
setattr(a,"g","G")
a.g = "G+"
something = a.a
Los nuevos codificadores a veces escriben código como este:
my_calculator.button_0 = tkinter.Button(root, text=0)
my_calculator.button_1 = tkinter.Button(root, text=1)
my_calculator.button_2 = tkinter.Button(root, text=2)
...
Luego, el codificador se queda con una pila de variables con nombre, con un esfuerzo de codificación de O ( m * n ), donde m es el número de variables con nombre yn es el número de veces que se debe acceder a ese grupo de variables (incluida la creación ). El principiante más astuto observa que la única diferencia en cada una de esas líneas es un número que cambia en base a una regla, y decide utilizar un bucle. Sin embargo, se atascan en cómo crear dinámicamente esos nombres de variables y pueden intentar algo como esto:
for i in range(10):
my_calculator.(''button_%d'' % i) = tkinter.Button(root, text=i)
Pronto descubren que esto no funciona.
Si el programa requiere una variable arbitraria de "nombres", un diccionario es la mejor opción, como se explica en otras respuestas. Sin embargo, si simplemente está tratando de crear muchas variables y no le importa referirse a ellas con una secuencia de enteros, probablemente esté buscando una list
. Esto es particularmente cierto si sus datos son homogéneos, como lecturas diarias de temperatura, puntajes semanales de cuestionarios o una cuadrícula de widgets gráficos.
Esto se puede montar de la siguiente manera:
my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))
Esta list
también se puede crear en una línea con una comprensión:
my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
El resultado en cualquier caso es una list
poblada, con el primer elemento al que se accede con my_calculator.buttons[0]
, el siguiente con my_calculator.buttons[1]
, y así sucesivamente. El nombre de la variable "base" se convierte en el nombre de la list
y el identificador variable se utiliza para acceder a ella.
Finalmente, no olvide otras estructuras de datos, como el set
, esto es similar a un diccionario, excepto que cada "nombre" no tiene un valor adjunto. Si simplemente necesita una "bolsa" de objetos, esta puede ser una gran elección. En lugar de algo como esto:
keyword_1 = ''apple''
keyword_2 = ''banana''
if query == keyword_1 or query == keyword_2:
print(''Match.'')
Tendrás esto:
keywords = {''apple'', ''banana''}
if query in keywords:
print(''Match.'')
Use una list
para una secuencia de objetos similares, un set
para una bolsa de objetos ordenada arbitrariamente o un dict
para una bolsa de nombres con valores asociados.
No es una buena idea. Si está accediendo a una variable global, puede usar globals()
.
>>> a = 10
>>> globals()[''a'']
10
Si desea acceder a una variable en el ámbito local, puede usar locals()
, pero no puede asignar valores al dict devuelto.
Una mejor solución es usar getattr
o almacenar sus variables en un diccionario y luego acceder a ellas por su nombre.
Puedes usar los diccionarios para lograr esto. Los diccionarios son almacenes de claves y valores.
>>> dct = {''x'': 1, ''y'': 2, ''z'': 3}
>>> dct
{''y'': 2, ''x'': 1, ''z'': 3}
>>> dct["y"]
2
Puede usar nombres de clave variable para lograr el efecto de variables variables sin el riesgo de seguridad.
>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
''eggs''
Para los casos en los que estás pensando en hacer algo como
var1 = ''foo''
var2 = ''bar''
var3 = ''baz''
...
una lista puede ser más apropiada que un dict. Una lista representa una secuencia ordenada de objetos, con índices enteros:
l = [''foo'', ''bar'', ''baz'']
print(l[1]) # prints bar, because indices start at 0
l.append(''potatoes'') # l is now [''foo'', ''bar'', ''baz'', ''potatoes'']
Para las secuencias ordenadas, las listas son más convenientes que los dictados con claves enteras, porque las listas admiten la iteración en orden de índice, slicing , append
y otras operaciones que requerirían una gestión de claves incómoda con un dict.
Si no desea usar ningún objeto, aún puede usar setattr()
dentro de su módulo actual:
import sys
current_module = module = sys.modules[__name__] # i.e the "file" where your code is written
setattr(current_module, ''variable_name'', 15) # 15 is the value you assign to the var
print(variable_name) # >>> 15, created from a string
Siempre que quiera usar variables variables, probablemente sea mejor usar un diccionario. Así que en lugar de escribir
$foo = "bar"
$$foo = "baz"
usted escribe
mydict = {}
foo = "bar"
mydict[foo] = "baz"
De esta manera, no sobrescribirá accidentalmente las variables existentes anteriormente (que es el aspecto de seguridad) y puede tener diferentes "espacios de nombres".
Tienes que usar globals()
construido en el método para lograr ese comportamiento:
def var_of_var(k, v):
globals()[k] = v
print variable_name # NameError: name ''variable_name'' is not defined
some_name = ''variable_name''
globals()[some_name] = 123
print variable_name # 123
some_name = ''variable_name2''
var_of_var(some_name, 456)
print variable_name2 # 456
Use la función incorporada getattr
para obtener un atributo en un objeto por nombre. Modificar el nombre según sea necesario.
obj.spam = ''eggs''
name = ''spam''
getattr(obj, name) # returns ''eggs''
a = ''hi''
# the expression below is a dynamic way of saying: b = ''by''
locals()[''b''] = ''by''
print(a)
# ''hi''
print(b)
# ''by''