python:使用vars()将字符串赋给变量

Python: Using vars() to assign a string to a variable

我发现能够在运行时创建新的变量,并创建结果的字典以便以后处理非常有用,例如,写入文件:

1
2
3
4
5
myDict = {}
for i in range (1,10):
    temp ="variable"+str(i)
    vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
    myDict[temp] = vars(temp)

它创建字典条目[result1:data1],我可以用mydict[result1]调用它。我一直在使用vars(),但没有真正理解我在做什么。我认为vars()返回一个带有局部变量(?)的字典。和

vars()[x] = y

是否创建[X:Y]的新字典条目?

我有一个脚本,我在其中传递一个用input1:data1,input2:data2编写的字典,我使用这个方法迭代所有值,存储所有结果,并将其输出到一个文件。这个代码位在一个类中的一个函数内,并且正在工作。

我的困惑源于我读了很多关于locals()不应该被弄乱的文章,以及vars()是如何等价的(?)到locals()或globals()。

所以我的问题是(至少)双重的:

1.vars()具体做什么,特别是vars()[x]=y做什么,

2.这本字典的范围是什么(当我写更大的程序时,我需要记住的是什么)

3.这是否是良好的编程实践。

事先谢谢!


创建变量序列的方法

如果需要变量序列,请创建一个序列。而不是试图创建独立变量,如:

1
2
3
4
variable0
variable1
variable2
variable3

您应该考虑创建一个list。这与S.Lott的建议类似(S.Lott通常有很好的建议),但在您的for循环上映射得更整齐:

1
2
3
sequence = []
for _ in xrange(10):
    sequence.append(function_that_returns_data())

(注意,我们丢弃了循环变量(_)。我们只想通过10次。)

然后您的数据将可用为:

1
2
3
4
5
6
sequence[0]
sequence[1]
sequence[2]
sequence[3]
[...]
sequence[9]

作为额外的奖励,您可以:

1
2
for datum in sequence:
    process_data(datum)

一开始,你可能会因为你的序列从0开始而抽搐。你可以通过各种扭曲让你的实际数据从1开始,但这比它的价值更痛苦。我建议您习惯使用零基列表。一切都是围绕着它们建造的,它们很快就开始感觉自然了。

vars()和locals()。

现在,回答你问题的另一部分。vars()locals()提供对python创建的变量的低级访问。因此以下两行是等效的。

1
2
locals()['x'] = 4
x = 4

vars()['x']的范围与x的范围完全相同。locals()vars()的一个问题是,它将允许您将那些您无法通过正常方式从命名空间中获得的内容放入命名空间中。所以您可以这样做:locals()[4] = 'An integer',但如果不再次使用局部名称空间,就无法恢复,因为局部名称空间(与所有python名称空间一样)只用于保存字符串。

1
2
3
4
5
6
7
8
9
10
11
12
>>> x = 5
>>> dir()
['__builtins__', '__doc__', '__name__', 'x']
>>> locals()[4] = 'An integer'
>>> dir()
[4, '__builtins__', '__doc__', '__name__', 'x']
>>> x
5
>>> 4
4
>>> locals()[4]
'An integer'

注意4不会返回与locals()[4]相同的内容。这可能会导致一些意外的、难以调试的问题。这是避免使用locals()的原因之一。另一个原因是,仅仅做一些Python提供的简单、不易出错的方法(比如创建一系列变量)通常会很复杂。


改为这样做。这更简单。

1
2
3
4
myDict = {}
for i in range (1,10):
    temp ="variable"+str(i)
    myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.

这就是你所需要做的。

结果将是myDict['variable1']myDict['variable9']

你很少需要vars()locals()。停止使用它们,使用普通变量和普通字典。尽量避免不理解的事情,坚持简单明了的事情。


在Vars的帮助下,

vars(...)
vars([object]) -> dictionary

1
2
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.

您使用它时没有var,所以让我们看看本地人的帮助()。

locals(...)
locals() -> dictionary

1
Update and return a dictionary containing the current scope's local

variables.

所以这就回答了前两个问题。vars()将字典返回到以变量名称作为字符串索引的局部变量。范围是本地的。

我不确定第三个问题,但它看起来确实有点像黑客,这不是一个好迹象。我想如果你小心地只在正确的范围内使用它,你就可以通过它。


jcdyer很好地解释了这些概念,justin peel清楚地说明了vars()locals()的作用。但一个小例子总是能加速理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Bull(object):

    def __init__(self):
        self.x = 1
        self.y ="this"

    def __repr__(self):
        return"Bull()"

    def test1(self):
        z = 5
        return vars()

    def test2(self):
        y ="that"
        return vars(self)

    def test3(self):
        return locals()

    def test4(self):
        y = 1
        return locals()

if __name__ =="__main__":
    b = Bull()
    print b.test1()
    print b.test2()
    print b.test3()
    print b.test4()
    print vars(b).get("y")

结果是:

1
2
3
4
5
{'self': Bull(), 'z': 5}
{'y': 'this', 'x': 1}
{'self': Bull()}
{'y': 1, 'self': Bull()}
this

我可以回答第3个问题:这不是很好的编程实践。我不太清楚您想要完成什么,但我确信有一种更优雅的方法可以不用使用locals()(根据交互python shell中的help(vars),它与vars()相同)。


以这种方式使用vars/locals或globals是(a)糟糕的做法,(b)并非在所有情况下都有效。有关详细信息,请参阅动态设置局部变量。底线:只要用听写——这就是他们的目的。