【问题标题】:Python: Using vars() to assign a string to a variablePython:使用 vars() 将字符串分配给变量
【发布时间】:2011-01-20 05:27:07
【问题描述】:

我发现能够在运行时创建新变量并创建结果字典以供以后处理(即写入文件)非常有用:

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

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

vars()[x] = y

创建一个新的字典条目 [x:y] ?

我有一个脚本,我传入一个用 {input1:data1,input2:data2} 准备的字典,我使用这个方法遍历所有值,存储所有结果,并将其输出到文件。这段代码在一个类的函数内部,并且正在工作。

我的困惑来源是我已经阅读了关于如何不应该混淆 locals() 以及 vars() 如何等效于 locals() 或 globals() 的各种帖子。

所以我的问题是(至少)两个方面:

1. vars(),或者特别是 vars()[x] = y 到底是做什么的,

2.这本词典的作用域是什么(写大程序时需要注意什么

3.这是否是好的编程习惯。

提前致谢!

【问题讨论】:

    标签: python string dictionary variables


    【解决方案1】:

    创建变量序列的pythonic方法

    如果您想要一个变量序列,请创建一个序列。而不是尝试创建独立变量,例如:

    variable0
    variable1
    variable2
    variable3
    

    您应该考虑创建一个list。这类似于 S.Lott 的建议(S.Lott 通常有很好的建议),但更巧妙地映射到您的 for 循环:

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

    (请注意,我们丢弃了循环变量 (_)。我们只是试图获得 10 次通过。)

    那么您的数据将以下列形式提供:

    sequence[0]
    sequence[1]
    sequence[2]
    sequence[3]
    [...]
    sequence[9]
    

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

    for datum in sequence:
        process_data(datum)
    

    一开始,您可能会对序列从 0 开始感到不安。您可以通过各种扭曲来让实际数据从 1 开始,但这比它的价值更痛苦。我建议习惯于使用从零开始的列表。一切都是围绕着它们构建的,它们很快就会变得自然。

    vars() 和 locals()

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

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

    vars()['x'] 的作用域与x 的作用域完全相同。 locals()(或vars())的一个问题是,它会让您将无法通过正常方式从名称空间中取出的东西放入名称空间中。所以你可以做这样的事情:locals()[4] = 'An integer',但是你不能在不再次使用本地的情况下恢复它,因为本地命名空间(与所有 python 命名空间一样)仅用于保存字符串。

    >>> 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 提供的更简单、不易出错的方法(比如创建变量序列)通常会很复杂。

    【讨论】:

    • 我认为vars()['x'] = 4x = 4 实际上只是在某些时候是等价的。如果您在函数中执行此操作,并且没有在其他位置设置x,并且该函数已被编译器优化,那么稍后在函数中正常查找x(即y = x + 2)将不起作用。我认为编译器缓存了它可以看到的变量(可能是在编译时定义的),并且没有考虑到这种恶作剧。如果在函数中添加 exec 语句,则编译器不会尝试优化函数。
    • 感谢您的深思熟虑的回答,对于按顺序排列的基准:函数(基准)看起来非常有用。今天学到了很多东西,谢谢!
    • 要查找有关该构造的更多信息,请查找“python 迭代器”
    • 设置 locals()[...] 具有未定义的行为 stackoverflow.com/questions/8028708/…
    • 为什么不用(Notice that we don't even need the i in the for loop. We're just trying to get 10 passes.) 而只是使用for _ in xrange(10):
    【解决方案2】:

    改为这样做。它更简单。

    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(),这可能是因为当我逐行测试代码时能够在 IDLE 状态下立即调用变量感觉很好。感谢您的回答!
    【解决方案3】:

    来自 vars 的帮助,

    变量(...) vars([object]) -> 字典

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

    你是在不使用 vars 的情况下使用它,所以让我们看看 locals() 的帮助

    本地人(...) locals() -> 字典

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

    变量。

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

    我不确定第三个问题,但它看起来确实有点像 hack,这不是一个好兆头。我想如果你小心谨慎地只在正确的范围内使用它,你就可以应付它。

    【讨论】:

    • 我被迷惑了,忘了寻求帮助()。谢谢,
    【解决方案4】:

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

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

    结果:

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

    【讨论】:

      【解决方案5】:

      我可以回答第 3 点:这不是好的编程习惯。我不完全明白你想要完成什么,但我确信有一种更优雅的方法可以在不使用 locals() 的情况下完成它(这与交互式 Python shell 中的 help(vars) 中的 vars() 相同)。

      【讨论】:

        【解决方案6】:

        以这种方式使用 vars / locals 或 globals 是 (a) 糟糕的做法,并且 (b) 并非在所有情况下都有效。有关详细信息,请参阅Dynamically set local variable。底线:只需使用 dicts - 这就是它们的用途。

        【讨论】:

          【解决方案7】:

          我也在很多地方寻找这个答案。到目前为止我看到的最好的是:

          var_list = ["Var_Name{}".format(i) for i in range(1,100)]
          

          【讨论】:

          • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
          猜你喜欢
          • 1970-01-01
          • 2019-02-08
          • 2013-02-23
          • 2019-12-05
          • 1970-01-01
          • 2013-04-18
          • 1970-01-01
          • 2019-02-20
          • 1970-01-01
          相关资源
          最近更新 更多