初始化顺序导致 class 个实例问题

Initialization order causes class instance problems

我只是想 post 我目前所拥有的并尝试描述问题。

下面的脚本跟踪具有自定义属性的转换对象。它创建了一个接口,可以轻松 __get____set__ 到 Maya 节点的属性。这使得将属性值保存到场景中变得容易,以便将来可以加载场景。在脚本中,我使用 OpenMaya 来跟踪 dagObject,但简化为先尝试解决问题。如果您想使用此代码,请查看 MDagPath 和 MSelectionList。

现在.. Attributes() 需要在 __init__ 之外声明才能正常工作。 Attributes() 就像现在一样,在创建时需要一个 Transform()。 如果我在 Clip() 中的 __init__ 之外创建 Transform(),生成的 Transform() 实例将引用通过此方法创建的最新 Transform()(图片)

不能post没有声誉的图像,所以描述: 名为 _new_anim_、_new_anim_1、_new_anim_2 的三个剪辑。 当下面的脚本运行时,列表的输出都是 _new_anim_2,这是最后一个初始化的转换。

__init__ 发生在 属性创建之后。 我需要将 __init__ Transform 实例传递给已初始化的属性实例。

如何?

clip.transform = correctTransform 似乎并不能取代对 correctTransfrom 的引用。我需要一种方法将 class 实例传递给在 __init__.

之外初始化的 class 变量
import maya.cmds as cmds

class Attribute(object):
    def __init__(self,transform,attr,*args):
        self.transform = transform
        self.attr = attr
        self.string = "string" in args
    def __set__(self, instance, value):
        if self.string:
            cmds.setAttr(self.transform.path()+"."+self.attr,value,dt="string")
        else:
            cmds.setAttr(self.transform.path()+"."+self.attr,value)
    def __get__(self, instance, owner):
        if self.string:
            return     cmds.getAttr(self.transform.path()+"."+self.attr,dt="string")
        return cmds.getAttr(self.transform.path()+"."+self.attr)

class Transform(object):
    def __init__(self):
        self.parent = ""
        self.name = ""
    def setObject(self,transform):
        self.parent = cmds.listRelatives(transform,p=1)[0]
        self.name = cmds.ls(transform,sn=1)[0]
    def path(self):
        return self.parent+"|"+self.name
    def getName(self):
        return cmds.ls(self.path(),sn=1)[0]
    def rename(self,value):
        self.name = cmds.ls(cmds.rename(self.path(),value),sn=1)[0]

class Clip(object):
    transform = Transform()
    start = Attribute(transform,"STA")
    end = Attribute(transform,"END")
    loop = Attribute(transform,"Loop")
    relative = Attribute(transform,"RelativeToStart")
    speedState = Attribute(transform,"SpeedState")
    speed = Attribute(transform,"SpeedVal")

    def __init__(self,transform):
        self.transform.setObject(transform)

如果我没有正确理解您的问题,您似乎希望 Clip class 中的 transform 变量成为特定于实例的值,但您有问题,因为它需要被您也添加到 ClipAttribute 描述符访问,需要声明为 class 变量。

我认为解决这个问题的方法是让 Attribute class 的 __get____set__ 方法在 instance 它们是传入的,而不是 self.

试试这个:

class Attribute(object):
    def __init__(self,attr,*args): # no transform parameter or instance variable
        self.attr = attr
        self.string = "string" in args
    def __set__(self, instance, value): # look up transform on instance, rather than self
        if self.string:
            cmds.setAttr(instance.transform.path()+"."+self.attr,value,dt="string")
        else:
            cmds.setAttr(instance.transform.path()+"."+self.attr,value)
    def __get__(self, instance, owner): # here too
        if self.string:
            return     cmds.getAttr(instance.transform.path()+"."+self.attr,dt="string")
        return cmds.getAttr(instance.transform.path()+"."+self.attr)

# Transform can stay the same, though you could merge set_object into __init__

class Clip(object):
    # no more transform class variable
    start = Attribute("STA") # no more transform argument passed to the Attributes
    end = Attribute("END")
    loop = Attribute("Loop")
    relative = Attribute("RelativeToStart")
    speedState = Attribute("SpeedState")
    speed = Attribute("SpeedVal")

    def __init__(self,transform):
        self.transform = Transform() # create transform as an instance variable
        self.transform.setObject(transform)