在动态生成列表名称时迭代列表

时间:2012-05-08 00:06:30

标签: python

如何遍历名称将动态生成的列表?

boneList_head =['def_neck', 'def_armbase']#hard coded list
itemType='head'# result of a user button press
...
def selectBones():
    global itemType
    bones =('boneList_'+itemType)# evaluates as a string , not name of a list
    for bone in bones:
        cmds.select(bone, tgl=True)

问题是 bones 被评估为字符串,当我需要它作为列表的名称进行评估时。

3 个答案:

答案 0 :(得分:7)

动态生成变量名称几乎总是一种糟糕的方法。使用字典!

bonedict = {'boneList_head': ['def_neck', 'def_armbase']}
itemType='head'

def selectBones(itemType):
    bones = bonedict['boneList_' + itemType]
    for bone in bones:
        cmds.select(bone, tgl=True)

请忽略我以前的答案(在我的编辑历史中可见),这是愚蠢的,甚至是愚蠢的。但我责怪它在动态变量名称生成上的愚蠢!

让我详细说明为什么动态变量名称生成是一个坏主意。

  1. 因为动态变量生成会掩盖变量名称定义。很难说出已定义的内容和未定义的内容,因此很容易意外地重新定义变量。这是潜在错误的主要来源。

  2. 因为动态变量操作会隐藏另一层混淆下的状态更改。在某种程度上,无论何时创建字典或列表,都是如此。但是一个期望列表和词典需要一些额外的思考。另一方面,变量名称应该简单易懂。当变量定义和重新定义需要深入思考时,就会出现问题。

  3. 因为动态变量生成会污染命名空间。如果你有很多变量需要自动生成它们,那么它们应该存在于它们自己的命名空间中,而不是在函数的本地中,而肯定不在全局命名空间中。在他的Linux内核风格指南中,Linus Torvalds建议如果一个函数有超过5-10个局部变量,you're doing something wrong

  4. 因为动态变量生成会导致high coupling,这是一件坏事。如果您将值分配给字典,您可以来回传递该字典,直到奶牛回家,所有人都必须知道的是该字典。如果在模块的全局命名空间中动态创建变量名,那么如果另一个模块想要访问这些变量名,则必须知道它们的生成方式,该模块中定义的其他变量等等。此外,传递变量变得更加复杂 - 您必须传递对模块本身的引用,可能使用sys.modules或其他可疑构造。

  5. 因为动态变量生成很难看。 eval看起来整洁干净,但事实并非如此。它可以做任何。可以做任何事情的函数都很糟糕,因为你不能乍一看他们在做什么这里。一个定义明确的函数可以完成一件事,而且做得很好;这样,每当你看到这个功能时,你就知道到底发生了什么。当您看到eval时,字面上可能会发生任何。从这个意义上说,eval就像goto。带有goto的{​​{3}}并非您无法正确使用它;对于goto的每一种可能的正确使用而言,有500,000,000种使用它的可怕错误方法。我甚至不会在这里讨论安全问题,因为最终,这不是eval的真正问题。

答案 1 :(得分:2)

我同意其他评论,你的方法可能不是最好的。但以下情况应该有效:

bones = eval('boneList_' + itemType)

这将在“boneList_head”上运行python解释器,并返回列表。

注意:正如Adam Mihalcin在评论中提到的那样,您应该非常小心只对您信任或已经验证的数据运行eval。恶意用户可以将任意代码注入到itemType变量中以访问操作系统等。

答案 2 :(得分:0)

这是一个丑陋的黑客,但它的工作原理......(当然,你需要获得正确的模块)

import sys
boneList_head =['def_neck', 'def_armbase']
itemType='head'
...
def selectBones():
    global itemType
    bones=vars(sys.modules["__main__"])['boneList_'+itemType]
    for bone in bones:
        cmds.select(bone, tgl=True)

这与其他人的说法并没有什么不同 - 我们正在使用vars构建一个字典来获取你想要的列表 - 为什么不只是传递字典(或正确的列表) )首先到函数selectBones?