0

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

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)

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

4

3 回答 3

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 个局部变量,那么你做错了什么

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

  5. 因为动态变量生成是丑陋的。eval看起来干净整洁,但实际上并非如此。它可以做任何事情。可以做任何事情的函数是不好的,因为你无法一眼看出它们在这里做什么。定义明确的函数只做一件事,而且做得很好;这样,每当您看到该功能时,您就可以确切地知道发生了什么。当您看到时eval,实际上任何事情都可能发生。从这个意义上说,eval就像goto问题goto在于您无法正确使用它;就是为了每一种可能的正确使用goto,有 500,000,000 种可怕的错误使用方法。我什至不会在这里讨论安全问题,因为归根结底,这不是eval.

于 2012-05-08T00:10:44.037 回答
2

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

bones = eval('boneList_' + itemType)

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

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

于 2012-05-08T00:21:14.473 回答
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地方?

于 2012-05-08T00:16:21.957 回答