您可以使用词典来完成此操作。字典是键和值的存储。
>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2
您可以使用变量键名来获得变量变量的效果,而不会带来安全隐患。
>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'
对于您正在考虑做类似事情的情况
var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...
列表可能比字典更合适。列表代表对象的有序序列,具有整数索引:
l = ['foo', 'bar', 'baz']
print(l[1]) # prints bar, because indices start at 0
l.append('potatoes') # l is now ['foo', 'bar', 'baz', 'potatoes']
对于有序序列,列表比带有整数键的字典更方便,因为列表支持按索引顺序进行迭代, slicing ,append
和其他需要使用dict进行笨拙的密钥管理的操作。
使用内置的 getattr
函数通过名称获取对象的属性。根据需要修改名称。
obj.spam = 'eggs'
name = 'spam'
getattr(obj, name) # returns 'eggs'
这不是一个好主意。如果要访问全局变量,则可以使用 globals()
< / a>。
>>> a = 10
>>> globals()['a']
10
如果您想在本地范围内访问变量,则可以使用 locals()
,但是您不能为返回的字典指定值。
一个更好的解决方案是使用getattr
或将变量存储在字典中,然后按名称访问它们。
每当您要使用变量时,最好使用字典。所以不用写
$foo = "bar"
$$foo = "baz"
您写
mydict = {}
foo = "bar"
mydict[foo] = "baz"
这样,您就不会意外覆盖以前存在的变量(这是安全方面),并且可以有不同的"命名空间"。
新编码员有时会编写如下代码:
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)
...
然后,使编码器剩下一堆命名变量,编码工作量为O( m * n ),其中 m 是命名变量的数量, n 是需要访问(包括创建)变量组的次数。更加精明的初学者观察到,这些行中的每一行的唯一区别是根据规则而变化的数字,并决定使用循环。但是,他们陷入了如何动态创建这些变量名的困境,并且可能会尝试如下操作:
for i in range(10):
my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)
他们很快发现这行不通。
如果程序需要任意变量"名称",则字典是最佳选择,如其他答案所述。但是,如果您只是尝试创建许多变量,而又不介意使用整数序列来引用它们,则可能是在寻找list
。如果您的数据是同质的,例如每天的温度读数,每周的测验分数或图形小部件网格,则尤其如此。
可以如下组装:
my_calculator.buttons = []
for i in range(10):
my_calculator.buttons.append(tkinter.Button(root, text=i))
此list
也可以一行一行地创建并理解:
my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
无论哪种情况,结果都是填充的list
,第一个元素通过my_calculator.buttons[0]
访问,下一个元素通过my_calculator.buttons[1]
,依此类推。 "基本"变量名称成为list
的名称,并且使用可变标识符来访问它。
最后,不要忘记其他数据结构,例如set
-这类似于字典,不同之处在于每个"名称"都没有附加值。如果您只需要一个"袋"的对象,这可能是一个不错的选择。而不是这样的:
keyword_1 = 'apple'
keyword_2 = 'banana'
if query == keyword_1 or query == keyword_2:
print('Match.')
您将拥有:
keywords = {'apple', 'banana'}
if query in keywords:
print('Match.')
将list
用于一系列相似的对象,将set
用于任意排序的对象包,或者将dict
用于对象一袋带有相关值的名称。
除了字典,您还可以使用 namedtuple
从集合模块中,这使访问更加容易。
例如:
# 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)
SimpleNamespace
类可以可用于使用setattr
或子类SimpleNamespace
创建新属性,并创建自己的函数以添加新属性名称(变量)。
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a
如果您不想使用任何对象,仍可以在当前模块内使用setattr()
:
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
使用globals()
实际上,您可以动态地将变量分配给全局范围,例如,如果要在全局范围内访问10个变量,则i_1
,i_2
... <代码>
i_10 :
代码>
for i in range(10):
globals()['i_{}'.format(i)] = 'a'
这将为所有这10个变量分配一个" a",当然您也可以动态更改该值。现在可以像访问其他全局声明的变量一样访问所有这些变量:
>>> i_5
'a'
我正在回答这个问题:如何在字符串中给定变量名称的情况下获取变量的值?,该变量作为重复项关闭,并带有指向该问题的链接。
如果所讨论的变量是对象的一部分(例如,类的一部分),则可以使用hasattr
,getattr
和< code> setattr 。
例如,您可以拥有:
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)
然后您可以做:
v = Variables()
v.get_var("foo")
"初始变量"
v.create_new_var(v.foo,"is actually not initial")
v.initial_variable
"实际上不是最初的"
您必须使用 globals()
在方法中以实现该行为:
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
共识是为此使用字典-参见其他答案。在大多数情况下,这是一个好主意,但是,由此产生了许多方面:
也就是说,我已经实现了变量变量管理器-类,它提供了一些以上想法。它适用于python 2和3。
您将使用该类像这样:
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'])
如果您只允许覆盖相同类型的变量:
myVars = VariableVariablesManager(enforceSameTypeOnOverride = True)
myVars['test'] = 25
myVars['test'] = "Cat" # <- raises Exception (different type on overwriting)
任何一组变量也可以包装在一个类中。通过在运行时通过__dict__属性直接访问内置字典,可以将"变量"变量添加到类实例中。
以下代码定义了Variables类,该类在构造期间将变量(在本例中为属性)添加到其实例。变量名来自指定的列表(例如,可能是由程序代码生成的):
# 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
我在python 3.7.3中都尝试过,可以使用globals()或vars()
>>> food #Error
>>> milkshake #Error
>>> food="bread"
>>> drink="milkshake"
>>> globals()[food] = "strawberry flavor"
>>> vars()[drink] = "chocolate flavor"
>>> bread
'strawberry flavor'
>>> milkshake
'chocolate flavor'
>>> globals()[drink]
'chocolate flavor'
>>> vars()[food]
'strawberry flavor'