• 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() 的最佳实践。你只需要保证全局和局部字典在后面代码访问时已经被初始化。

    别废话,拿你代码给我看。
  • 相关阅读:
    联考20200604 T2 宝石
    联考20200604 T1 旅游
    联考20200603 T2 排列
    [HAOI2017]八纵八横
    联考20200603 T1 解码
    [POI2011]KON-Conspiracy
    CF917D Stranger Trees
    CF1278F Cards
    CF809E Surprise me!
    NOI2016 循环之美
  • 原文地址:https://www.cnblogs.com/lvxueyang/p/13707499.html
Copyright © 2020-2023  润新知