List 在大型unicode列表上迭代需要很长时间吗?
我正在使用Autodesk Maya程序。 我制作了一个命名约定脚本,它将根据特定约定对每个项目进行命名。但是,我每次都会在场景中列出它,然后检查所选名称是否与场景中的任何当前名称匹配,然后让它重命名它,并在场景中再次检查是否存在重复的名称 然而,当我运行代码时,可能需要30秒到一分钟或更长的时间来运行所有代码。起初,我不知道是什么使我的代码运行缓慢,因为它在相对较低的场景量下运行良好。但是,当我在check场景代码中放入print语句时,我发现检查场景中的所有项目并检查重复项花费了很长时间 ls()命令提供场景中所有项目的unicode列表。这些项目可能相对较大,最多可达1000个或更多。如果场景中有适度数量的项目,则正常场景将比我目前拥有的测试场景(该列表中约有794个项目)大几倍 这要花这么长时间吗?我用来比较事物的方法是否低效?我不知道该怎么做,代码占用了太多的时间,我还想知道是否可能是代码中的其他内容,但这似乎就是它 下面是一些代码List 在大型unicode列表上迭代需要很长时间吗?,list,python-2.7,unicode,iteration,maya,List,Python 2.7,Unicode,Iteration,Maya,我正在使用Autodesk Maya程序。 我制作了一个命名约定脚本,它将根据特定约定对每个项目进行命名。但是,我每次都会在场景中列出它,然后检查所选名称是否与场景中的任何当前名称匹配,然后让它重命名它,并在场景中再次检查是否存在重复的名称 然而,当我运行代码时,可能需要30秒到一分钟或更长的时间来运行所有代码。起初,我不知道是什么使我的代码运行缓慢,因为它在相对较低的场景量下运行良好。但是,当我在check场景代码中放入print语句时,我发现检查场景中的所有项目并检查重复项花费了很长时间 l
class Name(object):
"""A naming convention class that runs passed arguments through user
dictionary, and returns formatted string of users input naming convention.
"""
def __init__(self, user_conv):
self.user_conv = user_conv
# an example of a user convention is '${prefix}_${name}_${side}_${objtype}'
@staticmethod
def abbrev_lib(word):
# a dictionary of abbreviated words is here, takes in a string
# and returns an abbreviated string, if not found return given string
@staticmethod
def check_scene(name):
"""Checks entire scene for same name. If duplicate exists,
Keyword Arguments:
name -- (string) name of object to be checked
"""
scene = ls()
match = [x for x in scene if isinstance(x, collections.Iterable)
and (name in x)]
if not match:
return name
else:
return ''
def convert(self, prefix, name, side, objtype):
"""Converts given information about object into user specified convention.
Keyword Arguments:
prefix -- what is prefixed before the name
name -- name of the object or node
side -- what side the object is on, example 'left' or 'right'
obj_type -- the type of the object, example 'joint' or 'multiplyDivide'
"""
prefix = self.abbrev_lib(prefix)
name = self.abbrev_lib(name)
side = ''.join([self.abbrev_lib(x) for x in side])
objtype = self.abbrev_lib(objtype)
i = 02
checked = ''
subs = {'prefix': prefix, 'name': name, 'side':
side, 'objtype': objtype}
while self.checked == '':
newname = Template (self.user_conv.lower())
newname = newname.safe_substitute(**subs)
newname = newname.strip('_')
newname = newname.replace('__', '_')
checked = self.check_scene(newname)
if checked == '' and i < 100:
subs['objtype'] = '%s%s' %(objtype, i)
i+=1
else:
break
return checked
类名(对象):
“”“运行通过用户传递的参数的命名约定类
字典,并返回用户输入命名约定的格式化字符串。
"""
定义初始化(自我、用户会话):
self.user\u conv=用户\u conv
#用户约定的一个示例是“${prefix}{name}{u${side}{u${objtype}”
@静力学方法
def abbrev_lib(word):
#这里有一本缩略词词典,包含一个字符串
#并返回一个缩写字符串,如果未找到,则返回给定字符串
@静力学方法
def check_场景(名称):
“”“检查整个场景是否具有相同的名称。如果存在重复项,
关键字参数:
名称--(字符串)要检查的对象的名称
"""
场景=ls()
match=[x代表场景中的x,如果isinstance(x,collections.Iterable)
及(姓名以x填列)]
如果不匹配:
返回名称
其他:
返回“”
def转换(自身、前缀、名称、侧面、对象类型):
“”“将有关对象的给定信息转换为用户指定的约定。
关键字参数:
前缀——名称前加了什么前缀
name——对象或节点的名称
side——对象位于哪一侧,例如“left”或“right”
对象类型——对象的类型,例如“关节”或“多分割”
"""
前缀=self.abbrev_lib(前缀)
name=self.abbrev_lib(name)
side=''.join([self.abbrev_lib(x)表示side中的x])
objtype=self.abbrev_lib(objtype)
i=02
选中=“”
subs={'prefix':前缀'name':名称'side':
“objtype”端:objtype}
而self.checked=='':
newname=模板(self.user\u conv.lower())
newname=newname.safe_替换(**subs)
newname=newname.strip(“”)
newname=newname.replace(“”“”,“”“”)
checked=self.check\u场景(新名称)
如果选中==''且i<100:
subs['objtype']='%s%s'(objtype,i)
i+=1
其他:
打破
退票
不要为每个名称运行ls
,而应该运行它一次,并将结果存储到集合中(无序列表-稍微快一点)。然后在运行check\u scene
def check_scene(self, name):
"""Checks entire scene for same name. If duplicate exists,
Keyword Arguments:
name -- (string) name of object to be checked
"""
if not hasattr(self, 'scene'):
self.scene = set(ls())
if name not in self.scene:
return name
else:
return ''
你做过很多次了吗?当self.checked=''
时,您可能会在中的每个迭代中拖拽数百或数千个项目的列表,这可能是罪魁祸首。FWIW打印在Maya中也非常慢,尤其是在打印一个长列表的情况下,因此无论发生什么情况,多次打印都会非常慢
我会尝试几件事来加快速度:
一次只能搜索一种类型-如果你现在只关心multilydivide
,为什么要在数百个随机节点中搜索
使用集合或字典来搜索,而不是列表-集合和字典使用哈希集,查找速度更快
如果您担心维护命名转换,那么一定要将其设计为抵抗Maya的默认行为,即附加数字后缀以保持名称唯一。任何不支持此功能的命名约定都将一直是一个麻烦,因为您无法阻止Maya在正常业务过程中执行此操作。另一方面,如果将其用于不同的实例,则根本不需要进行任何uniquification-只需在对象上使用rename()并捕获结果。存在的缺点是Maya不会为全局唯一性而重命名,而只为局部唯一性重命名-因此,如果要为非兄弟节点的对象命名唯一节点,则必须自己命名
下面是一些查找唯一节点名称的廉价代码:
def get_unique_scene_names (*nodeTypes):
if not nodeTypes:
nodeTypes = ('transform',)
results = {}
for longname in cmds.ls(type = nodeTypes, l=True):
shortname = longname.rpartition("|")[-1]
if not shortname in results:
results[shortname] = set()
results[shortname].add(longname)
return results
def add_unique_name(item, node_dict):
shortname = item.rpartition("|")[-1]
if shortname in node_dict:
node_dict[shortname].add(item)
else:
node_dict[shortname] = set([item])
def remove_unique_name(item, node_dict):
shortname = item.rpartition("|")[-1]
existing = node_dict.get(shortname, [])
if item in existing:
existing.remove(item)
def apply_convention(node, new_name, node_dict):
if not new_name in node_dict:
renamed_item = cmds.ls(cmds.rename(node, new_name), l=True)[0]
remove_unique_name(node, node_dict)
add_unique_name ( renamed_item, node_dict)
return renamed_item
else:
for n in range(99999):
possible_name = new_name + str(n + 1)
if not possible_name in node_dict:
renamed_item = cmds.ls(cmds.rename(node, possible_name), l=True)[0]
add_unique_name(renamed_item, node_dict)
return renamed_item
raise RuntimeError, "Too many duplicate names"
要在特定节点类型上使用它,只需在调用apply\u convention()
时提供正确的潜在名称即可。这会将场景中的所有关节(天真地!)重命名为“jnt_X”,同时保持后缀的唯一性。您可以做一些比这更聪明的事情,就像您的原始代码所做的那样-这只是确保树叶是唯一的:
joint_names= get_unique_scene_names('joint')
existing = cmds.ls( type='joint', l = True)
existing .sort()
existing .reverse()
# do this to make sure it works from leaves backwards!
for item in existing :
apply_convention(item, 'jnt_', joint_names)
# check the uniqueness constraint by looking for how many items share a short name in the dict:
for d in joint_names:
print d, len (joint_names[d])
但是,就像我说的,为那些该死的数字后缀制定计划,maya一直在未经许可的情况下制作它们,这样你就不能与它们对抗:(你做过任何分析,以找出时间花在哪里吗?不知道如何做,对python和使用IDE来说还是有点陌生。不过,我会看看是否可以查找。是的,我使用了cProfile.run(重新编译)