如何创build可变数量的variables?

我如何在Python中完成variablesvariables?

这里是一个详细的手册条目,例如: variablesvariables

一般来说,我听说这是一个糟糕的主意,这是Python中的一个安全漏洞。 真的吗?

使用字典来实现这一点。 字典是键和值的存储。

>>> dct = {'x': 1, 'y': 2, 'z': 3} >>> dct {'y': 2, 'x': 1, 'z': 3} >>> dct["y"] 2 

您可以使用variables键名称来实现variablesvariables的效果,而不存在安全风险。

 >>> x = "spam" >>> z = {x: "eggs"} >>> z["spam"] 'eggs' 

合理?

使用内置的getattr函数按名称获取对象的属性。 根据需要修改名称。

 obj.spam = 'eggs' name = 'spam' getattr(obj, name) # returns 'eggs' 

这不是一个好主意。 如果你正在访问一个全局variables,你可以使用globals()

 >>> a = 10 >>> globals()['a'] 10 

如果你想访问本地范围内的一个variables,你可以使用locals() ,但是你不能给返回的字典赋值。

更好的解决scheme是使用getattr或将variables存储在字典中,然后按名称访问它们。

无论何时你想使用variablesvariables,最好使用一个字典。 所以,而不是写作

 $foo = "bar" $$foo = "baz" 

你写

 mydict = {} foo = "bar" mydict[foo] = "baz" 

这样你不会不小心覆盖以前存在的variables(这是安全性方面),你可以有不同的“命名空间”。

您也可以使用collections模块中的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 

新的编码器有时会写这样的代码:

 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) ... 

编码器然后留下一堆命名variables,编码工作量为O( m * n ),其中m是命名variables的数量, n是该组variables需要访问的次数(包括创build)。 更敏锐的初学者观察到,每一行的唯一区别是一个基于规则而改变的数字,并决定使用一个循环。 然而,他们被困在如何dynamic创build这些variables名称,并可能会尝试这样的事情:

 for i in range(10): my_calculator.('button_%d' % i) = tkinter.Button(root, text=i) 

他们很快发现这是行不通的。

如果程序需要任意variables“名称”,字典是最好的select,正如其他答案中所解释的那样。 但是,如果您只是试图创build许多variables,并且不介意用一系列整数引用它们,那么您可能正在寻找一个list 。 如果您的数据是同质数据,例如每日温度读数,每周测验分数或graphics小部件网格,则情况尤其如此。

这可以组装如下:

 my_calculator.buttons = [] for i in range(10): my_calculator.buttons.append(tkinter.Button(root, text=i)) 

这个list也可以用理解的方式在一行中创build:

 my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)] 

两种情况下的结果都是填充list ,第一个元素用my_calculator.buttons[0]访问,下一个用my_calculator.buttons[1] ,依此类推。 “基本”variables名称成为list的名称,并使用不同的标识符来访问它。

最后,不要忘记其他数据结构,比如set – 这与字典类似,除了每个“名称”没有附加值。 如果你只需要一个“袋”的对象,这可能是一个很好的select。 而不是像这样的东西:

 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 ,一个任意sorting的对象包的集合,或一个包含相关值的名称的dict

你必须使用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 

一致的意见是为此使用一本字典 – 请参阅其他答案。 对大多数情况来说,这是一个好主意,但是由此产生了很多方面的问题:

  • 你会自己负责这本字典,包括垃圾收集(字典variables)等。
  • 对variablesvariables没有局部性或全局性,它取决于字典的整体性
  • 如果你想重命名一个variables名,你必须手动完成
  • 但是,你更灵活,例如
    • 你可以决定覆盖现有的variables或…
    • …select实现constvariables
    • 对不同types的覆盖引发exception
    • 等等

也就是说,我已经实现了一个variablespipe理器类,它提供了一些上述的想法。 它适用于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']) 

如果你想只允许覆盖相同types的variables:

 myVars = VariableVariablesManager(enforceSameTypeOnOverride = True) myVars['test'] = 25 myVars['test'] = "Cat" # <- raises Exception (different type on overwriting) 

任何一组variables也可以包装在一个类中。 通过__dict__属性直接访问内置字典,可以在运行时将“variables”variables添加到类实例中。

下面的代码定义了Variables类,它在构造过程中向其实例添加了variables(在本例中为属性)。 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(va, vb, vc) #will produce 100 100 100 

我正在回答这个问题: 如何得到一个variables的值在一个string中的名称? 这是作为一个重复closures与这个问题的链接。

如果所讨论的variables是对象的一部分(例如类的一部分),那么一些有用的函数就是hasattrgetattrsetattr

例如,你可以有:

 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") 

“initial_variable”

 v.create_new_var(v.foo,"is actually not initial") v.initial_variable 

“其实不是最初的”

SimpleNamespace类可用于使用setattrSimpleNamespace子类创build新的属性,并创build自己的函数来添加新的属性名称(variables)。

 from types import SimpleNamespace variables = {"b":"B","c":"C"} a = SimpleNamespace(**v) setattr(a,"g","G") ag = "G+" something = aa 

如果你不想使用任何对象,你仍然可以在当前模块中使用setattr()

 import sys current_module = module = sys.modules[__name__] # ie 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