我知道其他一些语言,如PHP,支持“变量变量名”的概念——也就是说,字符串的内容可以用作变量名的一部分。
我听说这通常是一个坏主意,但我认为它可以解决我的Python代码中的一些问题。
在Python中可以做这样的事情吗?会出什么问题?
如果您只是试图通过名称查找现有变量,请参见如何通过(字符串)名称选择变量。但是,首先考虑是否可以按照这个问题中的建议重新组织代码以避免这种需要。
我知道其他一些语言,如PHP,支持“变量变量名”的概念——也就是说,字符串的内容可以用作变量名的一部分。
我听说这通常是一个坏主意,但我认为它可以解决我的Python代码中的一些问题。
在Python中可以做这样的事情吗?会出什么问题?
如果您只是试图通过名称查找现有变量,请参见如何通过(字符串)名称选择变量。但是,首先考虑是否可以按照这个问题中的建议重新组织代码以避免这种需要。
当前回答
如果你不想使用任何对象,你仍然可以在当前模块中使用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
其他回答
大家的共识是使用字典来进行查询-请参阅其他答案。在大多数情况下,这是一个好主意,然而,这产生了许多方面:
您将自己负责这个字典,包括垃圾收集(indict变量)等。 变量变量没有局部性或全局性,这取决于字典的全局性 如果要重命名变量名,则必须手动执行 然而,你要灵活得多,例如: 您可以决定覆盖现有变量或… ... 选择实现const变量 针对不同类型的重写引发异常 等。
也就是说,我已经实现了一个变量变量管理器类,它提供了上面的一些想法。它适用于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)
您也可以使用collections模块中的namedtuple来代替字典,这使得访问更容易。
例如:
# using dictionary
variables = {}
variables["first"] = 34
variables["second"] = 45
print(variables["first"], variables["second"])
# using namedtuple
Variables = namedtuple('Variables', ['first', 'second'])
v = Variables(34, 45)
print(v.first, v.second)
如果你不想使用任何对象,你仍然可以在当前模块中使用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()。
>>> a = 10
>>> globals()['a']
10
如果想要访问局部作用域内的变量,可以使用locals(),但不能为返回的dict赋值。
更好的解决方案是使用getattr或将变量存储在字典中,然后按名称访问它们。
你必须使用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