Python 动态变量名定义与调用

动态变量名赋值

在使用 tkinter 时需要动态生成变量,如动态生成 var1…var10 变量。
使用 exec 动态赋值
exec 在 python3 中是内置函数,它支持 python 代码的动态执行。

for i in range(6):
  exec('var{} = {}'.format(i,i))

print(var0,var1,var2,var3,var4,var5)

运行结果如下:

0,1,2,3,4,5

利用命名空间动态赋值
在 Python 的命名空间中,将变量名与值存储在字典中,可以通过 locals(),globals() 函数分别获取局部命名空间和全局命名空间。

names = locals()
for i in range(5):
  names['n' + str(i)] = i

print(n0,n1,n2,n3,n4)

运行结果如下:

0 1 2 3 4

在类中使用动态变量
Python 的类对象的属性储存在的 dict 中。dict 是一个词典,键为属性名,值对应属性的值。

class Test_class(object):
  def __init__(self):
    names = self.__dict__
    for i in range(5):
      names['n' + str(i)] = i


t = Test_class()
print(t.__dict__)
print(t.n0,t.n1,t.n2,t.n3,t.n4)

运行结果如下:

{'n0': 0, 'n1': 1, 'n2': 2, 'n3': 3, 'n4': 4}
0 1 2 3 4

利用 exec 函数
同样地,可以使用 exec 调用变量

for i in range(5):
   exec('var{} = {}'.format(i, i))

for i in range(5):
  exec('print(var{},end=" ")'.format(i))

运行结果如下:

0 1 2 3 4 

利用命名空间
因为命令空间的 locals() 与 globals() 均会返回一个字典,利用字典的 get 方法获取变量的值。

for i in range(5):
   exec('var{} = {}'.format(i, i))

names = locals()
for i in range(5):
  print(names.get('var' + str(i)),end=' ')

运行结果如下:

0 1 2 3 4 

你想在使用范围内执行某个代码片段,并且希望在执行后所有的结果都不可见。

>>> a = 14
>>> exec('b = a + 1')
>>> print(b)
15

在一个函数中执行同样的代码:(会发生错误)

>>> def test():
...     a = 14
...     exec('b = a + 1')
...     print(b)
...
>>> test()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in test
NameError: global name 'b' is not defined
>>>

可以看出,最后抛出了一个NameError异常,就跟在 exec() 语句从没执行过一样。要是你想在后面的计算中使用到 exec() 执行结果的话就会有问题了。
为了修正这样的错误,你需要在调用 exec() 之前使用 locals() 函数来得到一个局部变量字典。
之后你就能从局部字典中获取修改过后的变量值了。例如:

>>> def test():
...     a = 13
...     loc = locals()
...     exec('b = a + 1')
...     b = loc['b']
...     print(b)
...
>>> test()
14
>>>

注意点:
默认情况下,exec() 会在调用者局部和全局范围内执行代码。然而,在函数里面,传递给 exec() 的局部范围是拷贝实际局部变量组成的一个字典。
因此,如果 exec() 如果执行了修改操作,这种修改后的结果对实际局部变量值是没有影响的。

>>> def test1():
...     x = 0
...     exec('x += 1')
...     print(x)
...
>>> test1()
0

上面代码里,当你调用 locals() 获取局部变量时,你获得的是传递给 exec() 的局部变量的一个拷贝。
通过在代码执行后审查这个字典的值,那就能获取修改后的值了。

>>> def test2():
...     x = 0
...     loc = locals()
...     print('before:', loc)
...     exec('x += 1')
...     print('after:', loc)
...     print('x =', x)
...
>>> test2()
before: {'x': 0}
after: {'loc': {...}, 'x': 1}
x = 0
>>>

仔细观察最后一步的输出,除非你将 loc 中被修改后的值手动赋值给x,否则x变量值是不会变的。
在使用 locals() 的时候,你需要注意操作顺序。每次它被调用的时候,locals() 会获取局部变量值中的值并覆盖字典中相应的变量。

>>> def test3():
...     x = 0
...     loc = locals()
...     print(loc)
...     exec('x += 1')
...     print(loc)
...     locals()
...     print(loc)
...
>>> test3()
{'x': 0}
{'loc': {...}, 'x': 1}
{'loc': {...}, 'x': 0}
>>>

注意最后一次调用 locals() 的时候x的值是如何被覆盖掉的。
作为 locals() 的一个替代方案,你可以使用你自己的字典,并将它传递给 exec() 。例如:

>>> def test4():
...     a = 13
...     loc = { 'a' : a }
...     glb = { }
...     exec('b = a + 1', glb, loc)
...     b = loc['b']
...     print(b)
...
>>> test4()
14
>>>

大部分情况下,这种方式是使用 exec() 的最佳实践。你只需要保证全局和局部字典在后面代码访问时已经被初始化。

别废话,拿你代码给我看。
原文地址:https://www.cnblogs.com/lvxueyang/p/13707499.html