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

时间:2009-09-03 12:37:48

标签: python variable-variables

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

以下是精心设计的手动条目,例如: Variable variables

我听说一般来说这是个坏主意,而且它是Python中的一个安全漏洞。这是真的吗?

17 个答案:

答案 0 :(得分:239)

您可以使用dictionaries来完成此操作。字典是键和值的存储。

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

列表可能比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']

对于有序序列,列表比带有整数键的词典更方便,因为列表支持按索引顺序迭代,slicingappend以及需要使用dict进行密钥管理的其他操作。

答案 1 :(得分:75)

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

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

答案 2 :(得分:58)

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

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

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

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

答案 3 :(得分:31)

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

$foo = "bar"
$$foo = "baz"
你写了

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

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

答案 4 :(得分:9)

您还可以使用集合模块中的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)

答案 5 :(得分: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

答案 6 :(得分: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

答案 7 :(得分:7)

您必须使用globals() built in method来实现此行为:

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

答案 8 :(得分:4)

使用globals()

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

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

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

>>> i_5
'a'

答案 9 :(得分:3)

我正在回答这个问题:How to get the value of a variable given its name in a string? 作为副本关闭,带有此问题的链接。

如果有问题的变量是对象的一部分(例如,类的一部分),那么一些有用的函数可以实现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
  

“实际上并非初始”

答案 10 :(得分:2)

# Python 3.8.2 (default, Feb 26 2020, 02:56:10)

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"; ?>

输出:

hello world
hello wow
hello world

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

# Python 3.8.2 (default, Feb 26 2020, 02:56:10)

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

输出:

locals():

hello world
hello wow
hello world


globals():

hello world
hello wow
hello world

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

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

创建变量和解包元组:

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

输出:

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

答案 11 :(得分:2)

这应该是非常危险的...... 但你可以使用 exec():

a = 'b=5'
exec(a)
c = b*2
print (c)

结果: 10

答案 12 :(得分:1)

共识是使用字典 - 请参阅其他答案。对于大多数情况来说这是一个好主意,但是,由此产生了许多方面:

  • 你自己要对这本词典负责,包括垃圾收集(in-dict变量)等。
  • 变量变量没有地点或全局,它取决于字典的全局性
  • 如果您想重命名变量名称,则必须手动执行
  • 然而,你更灵活,例如
    • 您可以决定覆盖现有变量或......
    • ...选择实施const变量
    • 提出覆盖不同类型的例外

那就是说,我已经实施了variable variables manager课程,它提供了上述一些想法。它适用于python 2和3。

您可以像这样使用the class

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)

答案 13 :(得分:1)

请参考以下示例来创建变量运行时。您可以使用import numpy as np import pandas as pd from scipy.stats import zscore df = pd.read_csv('./data.csv') df['price'] = df['price'].replace(0, np.nan) df['price'] = df.groupby('type').transform(lambda x: x.fillna(x.mean())) df['price_zscore'] = df[['price']].apply(zscore) # You need to apply score function on a DataFrame—not a Series.

globals()

在上面的示例中,我想在运行时创建三个变量:for i in range(3): globals() ['variable_'+str(i)] = i variable_0variable_1,其值分别为0、1和2。

variable_2

要访问在运行时创建的变量的值,可以使用variable_0 [Output]:0 variable_1 [Output]:1 variable_2 [Output]:2 方法,如下所示:

eval()

答案 14 :(得分:1)

有一种模拟变量容器的已知方法,它支持两种访问方法:通过变量名和字符串键。

class Vars:
    def __init__(self, **kw):
        self.__dict__.update(kw)

    def __getitem__(self, key):
        return self.__dict__[key]

    def __setitem__(self, key, val):
        self.__dict__[key] = val

    def __contains__(self, name):
        return name in self.__dict__

    def __nonzero__(self):
        return bool(self.__dict__)

    def __iter__(self):
        return iter(self.__dict__)

    def __len__(self):
        return len(self.__dict__)

    def __copy__(self):
        return self.__class__(**self.__dict__)

    def __repr__(self):
        return 'Vars(' + ', '.join('%s=%r' % (k,v) for k,v in self.__dict__.items()) + ')'

>>> vars = Vars()
>>> vars.a = 1
>>> vars['b'] = 2
>>> print(vars)
Vars(a=1, b=2)
>>> print(vars['a'], vars.b)
1 2
>>> print(tuple(vars))
('a', 'b')

答案 15 :(得分:0)

您可以使用内置功能vars()

>>> foo = 'bar'
>>> vars()[foo] = 'something'
>>> bar
'something'

答案 16 :(得分:-1)

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