如何遍历名称将动态生成的列表?
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 被评估为字符串,当我需要它作为列表的名称进行评估时。
答案 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)
请忽略我以前的答案(在我的编辑历史中可见),这是愚蠢的,甚至是愚蠢的。但我责怪它在动态变量名称生成上的愚蠢!
让我详细说明为什么动态变量名称生成是一个坏主意。
因为动态变量生成会掩盖变量名称定义。很难说出已定义的内容和未定义的内容,因此很容易意外地重新定义变量。这是潜在错误的主要来源。
因为动态变量操作会隐藏另一层混淆下的状态更改。在某种程度上,无论何时创建字典或列表,都是如此。但是一个期望列表和词典需要一些额外的思考。另一方面,变量名称应该简单易懂。当变量定义和重新定义需要深入思考时,就会出现问题。
因为动态变量生成会污染命名空间。如果你有很多变量需要自动生成它们,那么它们应该存在于它们自己的命名空间中,而不是在函数的本地中,而肯定不在全局命名空间中。在他的Linux内核风格指南中,Linus Torvalds建议如果一个函数有超过5-10个局部变量,you're doing something wrong。
因为动态变量生成会导致high coupling,这是一件坏事。如果您将值分配给字典,您可以来回传递该字典,直到奶牛回家,所有人都必须知道的是该字典。如果在模块的全局命名空间中动态创建变量名,那么如果另一个模块想要访问这些变量名,则必须知道它们的生成方式,该模块中定义的其他变量等等。此外,传递变量变得更加复杂 - 您必须传递对模块本身的引用,可能使用sys.modules
或其他可疑构造。
因为动态变量生成很难看。 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?