2015-09-09 1 views
1

Я собираюсь опубликовать то, что у меня есть, и попытаюсь описать проблему.Порядок инициализации вызывает проблемы экземпляра класса

В следующем скрипте отслеживается объект преобразования с пользовательскими атрибутами. Он создает интерфейс с легкостью __get__ и __set__ к атрибутам узла майи. Это упрощает сохранение значений атрибутов в сцену, которая может загружаться со сцены в будущем. В сценарии я использовал OpenMaya для отслеживания dagObject, но упростил сначала попытку решить проблему. Если вы хотите использовать этот код, просмотрите MDagPath и MSelectionList.

Теперь .. Attributes() необходимо заявить за пределами __init__ для правильной работы. Attributes() как они есть сейчас, требуется преобразование() при создании. Если я создаю Transform() снаружи на __init__ в Clip(), полученный Transform() экземпляр будет ссылаться на то, что последняя Transform() была создана этим методом (изображение)

Не можете прикреплять изображения без репутации, так описательно: три клипа под названием _new_anim_, _new_anim_1, _new_anim_2. Когда выполняется сценарий ниже, вывод из списка - это все _new_anim_2, который является последним преобразованием, которое было инициализировано.

__init__после Атрибуты создаются. Мне нужно передать экземпляр __init__Transform уже инициализированному экземпляру атрибута.

Как?

Выражение clip.transform = correctTransform не подходит для ссылки на correctTransfrom. Мне нужен способ передать экземпляр класса переменным класса, которые инициализируются вне __init__.

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) 

ответ

1

Если я понять ваш вопрос правильно, это выглядит, как вы хотите, transform переменные в классе Clip быть экземпляром конкретного значения, но у вас возникли проблемы, потому что он должен быть доступен по Attribute дескрипторы, которые вы также добавляете к Clip, которые должны быть объявлены как переменные класса.

Я думаю, что решение этой проблемы должно иметь __get__ и __set__ методы в Attribute класса ищут transform на 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) 
+0

Oooooh мою доброту. Спасибо!!! Это сработало. Небольшая настройка, но yay !!! –

+0

Возможно, вы захотите [прочитать на дескрипторах] (https://docs.python.org/3/reference/datamodel.html#implementing-descriptors), если вы собираетесь писать их самостоятельно. – Blckknght

+0

Я основывал все это на методе, который я использовал для Maya guis на techartsurvival.blogspot.com. Они прекрасно работают и используют очень похожий метод. Однако эта техника не нуждалась в передаче информации, подобной этому методу. Я искал информацию по этому вопросу. Просто не знал, как передать трансформацию. Я полностью замалчивал, что экземпляр - это источник, из которого передается вызов. –