标签归档:variable-variables

如何创建可变数量的变量?

问题:如何创建可变数量的变量?

如何在Python中完成变量变量?

例如,这是详尽的手动输入:变量变量

我听说这通常是个坏主意,这是Python中的一个安全漏洞。真的吗?

How do I accomplish variable variables in Python?

Here is an elaborative manual entry, for instance: Variable variables

I have heard this is a bad idea in general though, and it is a security hole in Python. Is that true?


回答 0

您可以使用字典来完成此任务。字典是键和值的存储。

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

列表可能比字典更合适。一个列表代表对象的有序序列,并带有整数索引:

lst = ['foo', 'bar', 'baz']
print(lst[1])           # prints bar, because indices start at 0
lst.append('potatoes')  # lst is now ['foo', 'bar', 'baz', 'potatoes']

对于有序序列,列表比整数键类型的字典更方便,因为列表支持迭代的索引顺序,切片append和其他操作,将需要尴尬密钥管理与字典。

You can use dictionaries to accomplish this. Dictionaries are stores of keys and values.

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

You can use variable key names to achieve the effect of variable variables without the security risk.

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

For cases where you’re thinking of doing something like

var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...

a list may be more appropriate than a dict. A list represents an ordered sequence of objects, with integer indices:

lst = ['foo', 'bar', 'baz']
print(lst[1])           # prints bar, because indices start at 0
lst.append('potatoes')  # lst is now ['foo', 'bar', 'baz', 'potatoes']

For ordered sequences, lists are more convenient than dicts with integer keys, because lists support iteration in index order, slicing, append, and other operations that would require awkward key management with a dict.


回答 1

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

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

Use the built-in getattr function to get an attribute on an object by name. Modify the name as needed.

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

回答 2

这不是一个好主意。如果要访问全局变量,则可以使用globals()

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

如果要访问本地作用域中的变量,可以使用locals(),但不能将值分配给返回的字典。

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

It’s not a good idea. If you are accessing a global variable you can use globals().

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

If you want to access a variable in the local scope you can use locals(), but you cannot assign values to the returned dict.

A better solution is to use getattr or store your variables in a dictionary and then access them by name.


回答 3

每当您想使用变量变量时,最好使用字典。所以不要写

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

你写

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

这样,您就不会意外覆盖以前存在的变量(这是安全方面),并且您可以拥有不同的“命名空间”。

Whenever you want to use variable variables, it’s probably better to use a dictionary. So instead of writing

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

you write

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

This way you won’t accidentally overwrite previously existing variables (which is the security aspect) and you can have different “namespaces”.


回答 4

新编码员有时会编写如下代码:

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

将a list用于一系列相似的对象,将a set用于任意排序的对象袋,或将a dict用于具有关联值的名称袋。

New coders sometimes write code like this:

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

The coder is then left with a pile of named variables, with a coding effort of O(m * n), where m is the number of named variables and n is the number of times that group of variables needs to be accessed (including creation). The more astute beginner observes that the only difference in each of those lines is a number that changes based on a rule, and decides to use a loop. However, they get stuck on how to dynamically create those variable names, and may try something like this:

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

They soon find that this does not work.

If the program requires arbitrary variable “names,” a dictionary is the best choice, as explained in other answers. However, if you’re simply trying to create many variables and you don’t mind referring to them with a sequence of integers, you’re probably looking for a list. This is particularly true if your data are homogeneous, such as daily temperature readings, weekly quiz scores, or a grid of graphical widgets.

This can be assembled as follows:

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

This list can also be created in one line with a comprehension:

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

The result in either case is a populated list, with the first element accessed with my_calculator.buttons[0], the next with my_calculator.buttons[1], and so on. The “base” variable name becomes the name of the list and the varying identifier is used to access it.

Finally, don’t forget other data structures, such as the set – this is similar to a dictionary, except that each “name” doesn’t have a value attached to it. If you simply need a “bag” of objects, this can be a great choice. Instead of something like this:

keyword_1 = 'apple'
keyword_2 = 'banana'

if query == keyword_1 or query == keyword_2:
    print('Match.')

You will have this:

keywords = {'apple', 'banana'}
if query in keywords:
    print('Match.')

Use a list for a sequence of similar objects, a set for an arbitrarily-ordered bag of objects, or a dict for a bag of names with associated values.


回答 5

除了字典之外,您还可以namedtuple在collections模块中使用它,这使访问更加容易。

例如:

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

Instead of a dictionary you can also use namedtuple from the collections module, which makes access easier.

For example:

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

回答 6

如果您不想使用任何对象,仍然可以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

If you don’t want to use any object, you can still use setattr() inside your current module:

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

回答 7

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

The SimpleNamespace class could be used to create new attributes with setattr, or subclass SimpleNamespace and create your own function to add new attribute names (variables).

from types import SimpleNamespace

variables = {"b":"B","c":"C"}
a = SimpleNamespace(**variables)
setattr(a,"g","G")
a.g = "G+"
something = a.a

回答 8

我正在回答这个问题:如何在字符串中给定变量名的情况下获取变量的值? 该链接作为重复链接关闭,并带有指向该问题的链接。

如果所讨论的变量是一个对象(例如一个类的一部分)的一部分,那么一些有用的功能,以实现准确是hasattrgetattr,和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

“实际上不是最初的”

I’m am answering the question: How to get the value of a variable given its name in a string? which is closed as a duplicate with a link to this question.

If the variables in question are part of an object (part of a class for example) then some useful functions to achieve exactly that are hasattr, getattr, and setattr.

So for example you can have:

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)

Then you can do:

v = Variables()
v.get_var("foo")

“initial_variable”

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

“is actually not initial”


回答 9

采用 globals()

实际上,您可以动态地将变量分配给全局范围,例如,如果要在全局范围内访问10个变量i_1i_2i_10

for i in range(10):
    globals()['i_{}'.format(i)] = 'a'

这将为所有这10个变量分配一个“ a”,当然您也可以动态更改该值。现在可以像访问其他全局声明的变量一样访问所有这些变量:

>>> i_5
'a'

Use globals()

You can actually assign variables to global scope dynamically, for instance, if you want 10 variables that can be accessed on a global scope i_1, i_2i_10:

for i in range(10):
    globals()['i_{}'.format(i)] = 'a'

This will assign ‘a’ to all of these 10 variables, of course you can change the value dynamically as well. All of these variables can be accessed now like other globally declared variable:

>>> i_5
'a'

回答 10

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

You have to use globals() built in method to achieve that behaviour:

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

回答 11

共识是为此使用字典-参见其他答案。在大多数情况下,这是一个好主意,但是,由此产生了许多方面:

  • 您将自己负责此词典,包括垃圾收集(命令变量)等。
  • 变量变量既不存在局部性也不存在全局性,这取决于字典的全局性
  • 如果要重命名变量名,则必须手动进行
  • 但是,您要灵活得多,例如
    • 您可以决定覆盖现有变量或…
    • …选择实现const变量
    • 对不同类型的覆盖提出exceptions
    • 等等

也就是说,我已经实现了变量变量管理器 -class,它提供了上述一些想法。它适用于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)

The consensus is to use a dictionary for this – see the other answers. This is a good idea for most cases, however, there are many aspects arising from this:

  • you’ll yourself be responsible for this dictionary, including garbage collection (of in-dict variables) etc.
  • there’s either no locality or globality for variable variables, it depends on the globality of the dictionary
  • if you want to rename a variable name, you’ll have to do it manually
  • however, you are much more flexible, e.g.
    • you can decide to overwrite existing variables or …
    • … choose to implement const variables
    • to raise an exception on overwriting for different types
    • etc.

That said, I’ve implemented a variable variables manager-class which provides some of the above ideas. It works for python 2 and 3.

You’d use the class like this:

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'])

If you wish to allow overwriting of variables with the same type only:

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

回答 12

我在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'


参考:https :
//www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936

I have tried both in python 3.7.3, you can use either globals() or 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'


Reference:
https://www.daniweb.com/programming/software-development/threads/111526/setting-a-string-as-a-variable-name#post548936


回答 13

任何一组变量也可以包装在一个类中。通过在运行时通过__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

Any set of variables can also be wrapped up in a class. “Variable” variables may be added to the class instance during runtime by directly accessing the built-in dictionary through __dict__ attribute.

The following code defines Variables class, which adds variables (in this case attributes) to its instance during the construction. Variable names are taken from a specified list (which, for example, could have been generated by program code):

# 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