List 在大型unicode列表上迭代需要很长时间吗?

List 在大型unicode列表上迭代需要很长时间吗?,list,python-2.7,unicode,iteration,maya,List,Python 2.7,Unicode,Iteration,Maya,我正在使用Autodesk Maya程序。 我制作了一个命名约定脚本,它将根据特定约定对每个项目进行命名。但是,我每次都会在场景中列出它,然后检查所选名称是否与场景中的任何当前名称匹配,然后让它重命名它,并在场景中再次检查是否存在重复的名称 然而,当我运行代码时,可能需要30秒到一分钟或更长的时间来运行所有代码。起初,我不知道是什么使我的代码运行缓慢,因为它在相对较低的场景量下运行良好。但是,当我在check场景代码中放入print语句时,我发现检查场景中的所有项目并检查重复项花费了很长时间 l

我正在使用Autodesk Maya程序。 我制作了一个命名约定脚本,它将根据特定约定对每个项目进行命名。但是,我每次都会在场景中列出它,然后检查所选名称是否与场景中的任何当前名称匹配,然后让它重命名它,并在场景中再次检查是否存在重复的名称

然而,当我运行代码时,可能需要30秒到一分钟或更长的时间来运行所有代码。起初,我不知道是什么使我的代码运行缓慢,因为它在相对较低的场景量下运行良好。但是,当我在check场景代码中放入print语句时,我发现检查场景中的所有项目并检查重复项花费了很长时间

ls()命令提供场景中所有项目的unicode列表。这些项目可能相对较大,最多可达1000个或更多。如果场景中有适度数量的项目,则正常场景将比我目前拥有的测试场景(该列表中约有794个项目)大几倍

这要花这么长时间吗?我用来比较事物的方法是否低效?我不知道该怎么做,代码占用了太多的时间,我还想知道是否可能是代码中的其他内容,但这似乎就是它

下面是一些代码

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(重新编译)