类中的Python字典列表不符合预期

时间:2016-07-29 13:32:12

标签: python list class dictionary maya

我似乎遇到的问题是,当我运行一个多次使用plusMinusAverage类的代码时(在我的情况下是一个for循环),该类的新实例保持对前面创建的pmaDicts列表的引用。之前的plu​​stMinusAverage创建并添加到它的末尾。

含义 (导致此问题的代码进一步低于以下)

things = []
for i in range(2):
    thing[i] = plusMinusAverage(count3D=2)
    print thing[i]
    print thing[i].values3D 
>>> (plusMinusAverage at 0x00NSTUFF1)
>>> [{"x":(attr.connection at 0x1234),"y":(attr.connection at 0x2345), etc..},
     {"x":(attr.connection at 0x3456),"y":(attr.connection at 0x4567), etc..}]
>>> (plusMinusAverage at 0x00NSTUFF2)
>>> [{"x":(attr.connection at 0x1234),"y":(attr.connection at 0x2345), etc..},
     {"x":(attr.connection at 0x3456),"y":(attr.connection at 0x4567), etc..},
     {"x":(attr.connection at 0x5678),"y":(attr.connection at 0x6789), etc..},
     {"x":(attr.connection at 0x7890),"y":(attr.connection at 0x8901), etc..}]

让我了解的是,它似乎打印出了对象,但随后列表显示为原始但有更多条目。我不明白为什么这个名单不是唯一的。

对于下面大量发布的代码感到抱歉,但我认为这个问题有一些细微之处,试图制作一个更简单的版本可能会引发一些对我的环境不起作用的解决方案,因为我不是某些问题确切存在,我将包括可能出错的所有相关部分。 ..plus也许在maya工作的人可以使用它来构建自己的shaderNode工具。

class Tracker2(object):
    dag = ""
    obj = ""
    getTime = "current"

    def setPathing(self):
        if self.nodeName == None:
            self.nodeName = cmds.createNode('transform')
            cmds.addAttr(self.nodeName, sn="type", ln="type", dt="string")
            cmds.setAttr(self.nodeName + ".type", type="string", keyable=0)
        sel = om.MSelectionList()
        sel.add(self.nodeName)
        self.obj = om.MObject()
        self.dag = om.MDagPath()
        sel.getDependNode(0, self.obj)
        try:
            sel.getDagPath(0, self.dag)
        except:
            pass

    def __init__(self):
        if not self.dag and not self.obj:
            self.setPathing()

    def fullpath(self):
        if self.dag and self.dag.fullPathName():
            return self.dag.fullPathName()
        return om.MFnDependencyNode(self.obj).name()

class shaderNode(Tracker2):
    def __init__(self):
        self.nodeName = cmds.shadingNode(self.type,au=1)
        Tracker2.__init__(self)

class connection(object):
    def __init__(self, attr, *args):
        self.attr = attr
    def __set__(self, instance, value):
        if isinstance(value,basestring):
            try:
                cmds.connectAttr(value,instance.fullpath()+"."+self.attr,f=1)
            except Exception as inst:
                cmds.warning(inst)
        elif not value:
            temp = cmds.listConnections(instance.fullpath()+"."+self.attr,s=1,d=0)
            if temp:
                cmds.disconnectAttr(instance.fullpath()+"."+self.attr, temp[0])
        else:
            cmds.warning("Set Connection: Source attribute is non-string value | "+value)
    def __get__(self, instance, owner):
        tempIn = cmds.listConnections(instance.fullpath()+"."+self.attr,s=1,d=0)
        tempIn = tempIn if tempIn else []
        tempOut = cmds.listConnections(instance.fullpath()+"."+self.attr,s=0,d=1)
        tempOut = tempOut if tempOut else []
        #returns list of [[incoming] , [outgoing]]
        return [tempIn,tempOut]

在单独的py文件中,其中包含连接的类作为attr

加载
class pmaDict(dict):
    def __init__(self,instance,*args,**kwargs):
        self.instance = instance
        dict.__init__(self,*args,**kwargs)
    def __getitem__(self, key):
        thing = dict.__getitem__(self,key)
        if key in self and isinstance(dict.__getitem__(self, key),attr.Attribute):
            return thing.__get__(self.instance,None)
        if key in self and isinstance(dict.__getitem__(self,key),attr.connection):
            return thing.__get__(self.instance,None)
        else:
            return dict.__getitem__(self,key)

    def __setitem__(self, key, value):
        thing = dict.__getitem__(self,key)
        if key in self and isinstance(dict.__getitem__(self,key),attr.Attribute):
            thing.__set__(self.instance,value)
        elif key in self and isinstance(dict.__getitem__(self,key),attr.connection):
            thing.__set__(self.instance, value)
        else:
            dict.__setitem__(self,key,value)

class plusMinusAvg(attr.shaderNode):
    type = "plusMinusAverage"
    values1D = []
    values2D = []
    values3D = []

    def addInput1D(self):
        i = len(self.values1D)
        print self
        cmds.setAttr(self.fullpath() + ".input1D[" + str(i) + "]", 0)
        newInput = pmaDict(self,
                           {"x": attr.Attribute("input1D[" + str(i) + "]", "float"),
                            "x_con": attr.connection("input1D[" + str(i) + "]")})
        self.values1D.append(newInput)

    def addInput2D(self):
        i = len(self.values2D)
        print self
        cmds.setAttr(self.fullpath() + ".input2D[" + str(i) + "]", 0, 0, type="double2")
        newInput = pmaDict(self,
                           {"xy": attr.Attribute("input2D[" + str(i) + "]", "float"),
                            "x": attr.Attribute("input2D[" + str(i) + "].input2Dx", "float"),
                            "y": attr.Attribute("input2D[" + str(i) + "].input2Dy", "float"),
                            "xy_con": attr.connection("input2D[" + str(i) + "]"),
                            "x_con": attr.connection("input2D[" + str(i) + "].input2Dx"),
                            "y_con": attr.connection("input2D[" + str(i) + "].input2Dy")})
        self.values2D.append(newInput)

    def addInput3D(self):
        i = len(self.values3D)
        print self
        cmds.setAttr(self.fullpath()+".input3D["+str(i)+"]",0,0,0, type="double3")
        newInput = pmaDict(self,
                           {"xyz": attr.Attribute("input3D["+str(i)+"]","double3"),
                            "x": attr.Attribute("input3D["+str(i)+"].input3Dx","float"),
                            "y": attr.Attribute("input3D["+str(i)+"].input3Dy","float"),
                            "z": attr.Attribute("input3D["+str(i)+"].input3Dz","float"),
                            "xyz_con": attr.connection("input3D["+str(i)+"]"),
                            "x_con": attr.connection("input3D["+str(i)+"].input3Dx"),
                            "y_con": attr.connection("input3D["+str(i)+"].input3Dy"),
                            "z_con": attr.connection("input3D["+str(i)+"].input3Dz")})
        self.values3D.append(newInput)

    def __init__(self, count1D=0, count2D=0, count3D=0):
        attr.shaderNode.__init__(self)
        for i in range(count1D):
            self.addInput1D()
        for i in range(count2D):
            self.addInput2D()
        for i in range(count3D):
            self.addInput3D()

1 个答案:

答案 0 :(得分:1)

问题就在这里:

class plusMinusAvg(attr.shaderNode):
    type = "plusMinusAverage"
    values1D = []
    values2D = []
    values3D = []

您正在将列表指定为类属性。您通常习惯于这样的任务,因为如果您在方法调用中执行values1d = blah之类的操作,则会在self上隐式地进行赋值。但是,您永远不会进行另一项任务:您只需通过append__setitem__等方法使用类级别列表。因此,所有实例都使用在类对象中定义的相同列表。

要修复,请将三个列表分配移至__init__

self.values1D = []
self.values2D = []
self.values3D = []

这将确保每个实例都获得它自己的列表。为所有可变属性(例如列表和dicts)执行此操作,以避免将来出现相同类型的问题。