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

315 python variable-variables

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

这是一个精心设计的手动条目,例如:变量变量

我听说这是一个坏主意,但它是Python中的一个安全漏洞.真的吗?

小智 266

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

>>> dct = {'x': 1, 'y': 2, 'z': 3}
>>> dct
{'y': 2, 'x': 1, 'z': 3}
>>> dct["y"]
2
Run Code Online (Sandbox Code Playgroud)

您可以使用变量键名来实现变量的影响,而不会产生安全风险.

>>> x = "spam"
>>> z = {x: "eggs"}
>>> z["spam"]
'eggs'
Run Code Online (Sandbox Code Playgroud)

对于你想要做类似事情的情况

var1 = 'foo'
var2 = 'bar'
var3 = 'baz'
...
Run Code Online (Sandbox Code Playgroud)

列表可能比dict更合适.列表表示有序的对象序列,带有整数索引:

l = ['foo', 'bar', 'baz']
print(l[1])           # prints bar, because indices start at 0
l.append('potatoes')  # l is now ['foo', 'bar', 'baz', 'potatoes']
Run Code Online (Sandbox Code Playgroud)

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


Sil*_*ost 81

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

obj.spam = 'eggs'
name = 'spam'
getattr(obj, name)  # returns 'eggs'
Run Code Online (Sandbox Code Playgroud)


Nad*_*mli 65

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

>>> a = 10
>>> globals()['a']
10
Run Code Online (Sandbox Code Playgroud)

如果要访问本地范围中的变量,可以使用locals(),但不能为返回的dict赋值.

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

  • [`locals()`](https://docs.python.org/3/library/functions.html#locals) 的文档特别指出:“该字典的内容不应该**被修改。” (强调我的) (8认同)
  • ***locals().update({'new_local_var':'some local value'})*** 在 Python 3.7.6 中对我来说工作得很好;所以我不确定当你说你不能通过它赋值时你的意思是什么。 (3认同)
  • 它不起作用的原因是,至少在 CPython 上,CPython 为局部变量分配一个固定大小的数组,并且该数组的大小是在定义函数时确定的,而不是在函数运行时确定的,并且不能更改(访问真正的局部变量甚至不使用名称;名称在函数编译时被替换为数组的索引)。`locals()` 返回一个真正的 `dict`;在函数中,当您调用“locals()”时,“dict”是通过在数组中加载名称和关联值来创建的,它不会看到未来的更改。如果它发生变化,则您处于全局或类范围(使用“dict”范围\)。 (3认同)

sep*_*p2k 33

每当你想使用变量变量时,最好使用字典.所以不要写作

$foo = "bar"
$$foo = "baz"
Run Code Online (Sandbox Code Playgroud)

你写

mydict = {}
foo = "bar"
mydict[foo] = "baz"
Run Code Online (Sandbox Code Playgroud)

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


Tig*_*kT3 27

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

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)
...
Run Code Online (Sandbox Code Playgroud)

然后编码器留下一堆命名变量,编码努力为O(m*n),其中m是命名变量的数量,n是需要访问变量组的次数(包括创建) ).更精明的初学者观察到,每条线的唯一差异是基于规则而变化的数字,并决定使用循环.但是,他们仍然坚持如何动态创建这些变量名称,并可能尝试这样的事情:

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

他们很快发现这不起作用.

如果程序需要任意变量"名称",则字典是最佳选择,如其他答案中所述.但是,如果你只是想创建许多变量并且你不介意用一系列整数来引用它们,那么你可能正在寻找一个list.如果您的数据是同质的,例如每日温度读数,每周测验分数或图形小部件网格,则尤其如此.

这可以如下组装:

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

list也可以通过理解在一行中创建:

my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下的结果都是填充的list,第一个元素被访问my_calculator.buttons[0],下一个元素被访问my_calculator.buttons[1],依此类推."base"变量名称成为名称,list变量标识符用于访问它.

最后,不要忘记其他数据结构,例如set- 这类似于字典,除了每个"名称"都没有附加值.如果您只需要一个"袋子"的物体,这可能是一个很好的选择.而不是像这样的东西:

keyword_1 = 'apple'
keyword_2 = 'banana'

if query == keyword_1 or query == keyword_2:
    print('Match.')
Run Code Online (Sandbox Code Playgroud)

你会有这个:

keywords = {'apple', 'banana'}
if query in keywords:
    print('Match.')
Run Code Online (Sandbox Code Playgroud)

使用a list表示一系列相似的对象,a set表示任意排序的对象包,或者表示dict包含相关值的名称包.


Roc*_* Li 18

globals()

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

for i in range(10):
    globals()['i_{}'.format(i)] = 'a'
Run Code Online (Sandbox Code Playgroud)

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

>>> i_5
'a'
Run Code Online (Sandbox Code Playgroud)


mOm*_*ney 14

Python 中的可变变量

"""
<?php
$a = 'hello';
$e = 'wow'
?>
<?php
$$a = 'world';
?>
<?php
echo "$a ${$a}\n";
echo "$a ${$a[1]}\n";
?>
<?php
echo "$a $hello";
?>
"""

a = 'hello'  #<?php $a = 'hello'; ?>
e = 'wow'   #<?php $e = 'wow'; ?>
vars()[a] = 'world' #<?php $$a = 'world'; ?>
print(a, vars()[a]) #<?php echo "$a ${$a}\n"; ?>
print(a, vars()[vars()['a'][1]]) #<?php echo "$a ${$a[1]}\n"; ?>
print(a, hello) #<?php echo "$a $hello"; ?>
Run Code Online (Sandbox Code Playgroud)

输出:

hello world
hello wow
hello world
Run Code Online (Sandbox Code Playgroud)

使用 globals()、locals() 或 vars() 将产生相同的结果

#<?php $a = 'hello'; ?>
#<?php $e = 'wow'; ?>
#<?php $$a = 'world'; ?>
#<?php echo "$a ${$a}\n"; ?>
#<?php echo "$a ${$a[1]}\n"; ?>
#<?php echo "$a $hello"; ?>

print('locals():\n')
a = 'hello'
e = 'wow'
locals()[a] = 'world'
print(a, locals()[a])
print(a, locals()[locals()['a'][1]])
print(a, hello)

print('\n\nglobals():\n')
a = 'hello'
e = 'wow'
globals()[a] = 'world'
print(a, globals()[a])
print(a, globals()[globals()['a'][1]])
print(a, hello)
Run Code Online (Sandbox Code Playgroud)

输出:

locals():

hello world
hello wow
hello world


globals():

hello world
hello wow
hello world
Run Code Online (Sandbox Code Playgroud)

奖励(从字符串创建变量)

# Python 2.7.16 (default, Jul 13 2019, 16:01:51)
# [GCC 8.3.0] on linux2
Run Code Online (Sandbox Code Playgroud)

创建变量并解包元组:

g = globals()
listB = []
for i in range(10):
    g["num%s" % i] = i ** 10
    listB.append("num{0}".format(i))

def printNum():
    print "Printing num0 to num9:"
    for i in range(10):
        print "num%s = " % i, 
        print g["num%s" % i]

printNum()

listA = []
for i in range(10):
    listA.append(i)

listA = tuple(listA)
print listA, '"Tuple to unpack"'

listB = str(str(listB).strip("[]").replace("'", "") + " = listA")

print listB

exec listB

printNum()
Run Code Online (Sandbox Code Playgroud)

输出:

Printing num0 to num9:
num0 =  0
num1 =  1
num2 =  1024
num3 =  59049
num4 =  1048576
num5 =  9765625
num6 =  60466176
num7 =  282475249
num8 =  1073741824
num9 =  3486784401
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) "Tuple to unpack"
num0, num1, num2, num3, num4, num5, num6, num7, num8, num9 = listA
Printing num0 to num9:
num0 =  0
num1 =  1
num2 =  2
num3 =  3
num4 =  4
num5 =  5
num6 =  6
num7 =  7
num8 =  8
num9 =  9
Run Code Online (Sandbox Code Playgroud)


小智 10

您也可以使用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)
Run Code Online (Sandbox Code Playgroud)

  • 请记住,“namedtuple”是不可变的,因此它们与带有点符号的简单字典有点不同。话虽如此,这两个选项都提倡良好的设计原则,并且不会像本线程中一半的答案那样滥用全局名称空间。 (3认同)

小智 9

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
Run Code Online (Sandbox Code Playgroud)


pat*_*_ai 7

我正在回答这个问题:如何在字符串中获取给定名称的变量的值? 已作为副本关闭,并附有此问题的链接。

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

然后你可以这样做:

v = Variables()
v.get_var("foo")
Run Code Online (Sandbox Code Playgroud)

“初始变量”

v.create_new_var(v.foo,"is actually not initial")
v.initial_variable
Run Code Online (Sandbox Code Playgroud)

“实际上不是初始的”


Gui*_*ton 7

如果您不想使用任何对象,您仍然可以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
Run Code Online (Sandbox Code Playgroud)

  • `globals()` 可以做到这一点 (2认同)

And*_*yko 5

您必须使用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
Run Code Online (Sandbox Code Playgroud)


Khu*_*Ran 5

我在 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'
Run Code Online (Sandbox Code Playgroud)


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