【问题标题】:Maya Python single line class instance and class variable assignment?Maya Python单行类实例和类变量赋值?
【发布时间】:2017-04-05 21:19:13
【问题描述】:

我想做这样的事情,

things = [ node().path = x for x in cmds.ls(sl=1,l=1)]

但我收到了无效的语法错误。所以我不得不改用这个,

things = []
for i, thing in enumerate(cmds.ls(sl=1,l=1)):
    things.append(node())
    things[i].path = thing

第一个无效代码非常简洁和简短。第二个很乏味。如何获得一些代码,使我可以在不使用初始化的情况下在同一创建行中分配一个类变量。我正在避免初始化,因为这个类将被跨多个文件继承到许多其他类中,而我以前使用初始化的版本在导入太多包时会崩溃,导致未绑定的方法错误。

【问题讨论】:

  • 简短的回答是你不能那样做;您不能在列表理解中分配作业。而不是enumerate,我可能会创建一个node,将其path then append 设置到列表中。或者,也许您可​​以使用minimal reproducible example 扩展“breaks wrong”,我们可以通过听起来更直接的方法来帮助解决问题?
  • 我猜你可以写[n for n, i in ((node(), i) for i in cmds.ls(sl=1, l=1)) if setattr(n, 'path', i) is None],但我强烈建议你不要写
  • @jonrsharpe 不!用火烧它! ;) 您不仅将副作用与功能构造混合在一起,而且对您的病情也有副作用!
  • @juanpa.arrivillaga 进入黑暗的中心
  • 它正正看着我

标签: python maya


【解决方案1】:

不仅第一个示例语法无效,而且您尝试做的事情根本不合理:不要将列表理解与状态更改混合(即分配给对象属性)。随便@ 987654321@ 是,似乎处理您的问题的最佳方法是向node.__init__ 添加一个参数,允许您在实例化node 对象时设置path。然后你可以做things = [node(x) for x in cmds.ls(sl=1, l=1)]

因此,使用__init__ 的单个位置参数的最基本方法:

class Node(object):
    def __init__(self, path):
        self.path = path
...

things = [Node(x) for x in cmds.ls(sl=1, l=1)]

不过,更重要的是,使用 for 循环完全符合 Python 风格。试图让你的代码都是单行的,从根本上来说是一种误导。以下是我将如何使用您已有的内容并使其更加 Pythonic:

things = []
for path in cmds.ls(sl=1,l=1):
    n = node()
    n.path = path
    things.append(n)

以上内容完全是pythonic......

【讨论】:

  • 由于大写,列表理解不会执行:)
【解决方案2】:

原问题的原因与这个问题有关:Maya Python: Unbound Method due to Reload()。我找到的解决方案本质上是重新设计我的跟踪方法,使其不需要初始化,然后,为了避免未绑定错误,我创建了最接近其用途的初始化序列。

trackingMethod文件:

import maya.cmds as cmds
import maya.OpenMaya as om

class pathTracking(object):
    def setPathing(self, instance):
        sel = om.MSelectionList()
        sel.add(instance.nodeName)
        try:
            instance.obj = om.MObject()
            sel.getDependNode(0, instance.obj)
        except:
            cmds.warning(instance.nodeName + " is somehow invalid as an openMaya obj node.")
        try:
            instance.dag = om.MDagPath()
            sel.getDagPath(0,instance.dag)
        except:
            pass
    def __set__(self, instance, value):
        if isinstance(value,dict):
            if "dag" in value:
                instance.dag = value["dag"]
            if "obj" in value:
                instance.obj = value["obj"]
            if "nodeName" in value:
                instance.nodeName = value["nodeName"]
                self.setPathing(instance)
        else:
            if isinstance(value, basestring):
                instance.nodeName = value
                self.setPathing(instance)
    def __get__(self, instance, owner):
        if instance.dag and instance.dag.fullPathName():
            return instance.dag.fullPathName()
        return om.MFnDependencyNode(instance.obj).name()

class exampleNode(object):
    path = pathTracking()
    dag = None
    obj = None
    nodeName = ""
    someVar1 = "blah blah"

    def initialize(self,nodeName,obj,dag):
        if obj or dag:
            self.obj = obj
            self.dag = dag
        elif nodeName:
            self.path = nodeName
        else:
            return False
        return True

其他文件:

import trackingMethod as trm

circleExample(trm.exampleNode):
    def __init__(self,nodeName="",dag=None,obj=None):
        if not self.initialize(nodeName,obj,dag)
            self.path = cmds.circle()[0]

用这个方法我可以做到

circles = [circleExample(nodeName=x) for x in cmds.ls(sl=1,l=1)]

PS。我遇到了一些需要先初始化类的东西,然后才能创建它的一些位。下面是一个自定义字典,需要我在创建字典时将一个 self 实例传递给它。在与转换交互的每个类中重新创建这些 dict 结构将是乏味的。解决方案是将这些依赖类初始化放入转换类中的一个函数中。这样,最终类继承了创建字典的函数,并可以在它们的 init 中调用它。这避免了当您有多个文件从单个类继承时中断的整个俄罗斯嵌套娃娃 init 语句。

虽然这个解决方案对某些人来说似乎很明显,但我只是想解决一个鸡蛋情况的方法,即需要初始化类以获取自我,但由于未绑定方法而无法初始化类错误。

class sqetDict(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(thing,(connection,Attribute,xform)):
            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(thing,(connection,Attribute,xform)):
            thing.__set__(self.instance,value)
        else:
            dict.__setitem__(self,key,value)

这些 dicts 会这样初始化:

def enableDicts(self):
    self.connection = sqetDict(self, {"txyz": connection("translate"), "tx": connection("tx"),
                                      "ty": connection("ty"), "tz": connection("tz"),
                                      "rxyz": connection("rotate"),
                                      "rx": connection("rx"), "ry": connection("ry"), "rz": connection("rz"),
                                      "sxyz": connection("scale"),
                                      "sx": connection("sx"), "sy": connection("sy"), "sz": connection("sz"),
                                      "joxyz": connection("jointOrient"),
                                      "jox": connection("jox"), "joy": connection("joy"), "joz": connection("joz"),
                                      "worldMatrix": connection("worldMatrix"),
                                      "worldInvMatrix": connection("worldInverseMatrix"),
                                      "parentInvMatrix": connection("parentInverseMatrix")})
    self.value = sqetDict(self, {"txyz": Attribute("translate", "double3"),
                                 "tx": Attribute("tx", "float"), "ty": Attribute("ty", "float"),
                                 "tz": Attribute("tz", "float"),
                                 "rxyz": Attribute("rotate", "double3"),
                                 "rx": Attribute("rx", "float"), "ry": Attribute("ry", "float"),
                                 "rz": Attribute("rz", "float"),
                                 "sxyz": Attribute("scale", "double3"),
                                 "sx": Attribute("sx", "float"), "sy": Attribute("sy", "float"),
                                 "sz": Attribute("sz", "float"),
                                 "joxyz": Attribute("jointOrient", "double3"),
                                 "jox": Attribute("jox", "float"), "joy": Attribute("joy", "float"),
                                 "joz": Attribute("joz", "float"),
                                 "rotOrder": Attribute("rotateOrder", "string"),
                                 "worldMatrix": Attribute("worldMatrix", "matrix"),
                                 "worldInvMatrix": Attribute("worldInverseMatrix", "matrix"),
                                 "parentInvMatrix": Attribute("parentInverseMatrix", "matrix"),
                                 "rotatePivot": Attribute("rotatePivot", "double3"),
                                 "visibility": Attribute("visibility", "long")})
    self.xform = sqetDict(self, {"t": xform("t"), "ro": xform("ro"), "s": xform("s")})

我的连接类在发送一个值时执行 cmds.connectAttr,它以字典形式返回连接的各种属性,例如 {"in": "in connection", "out":["outConn1","outCon2 ",etc..], "path":"fullpath name to attribute"}.所以你可以做类似的事情,thingA.connection["txyz"] = thingB.connection["txyz"]["path"] 来连接两个对象的相对平移。

我的 Attribute 类允许设置和获取属性值,例如 temp = thing.value["txyz"] 结果为 temp = (value,value,value),而 thing.value["txyz"]=(0, 0,0) 会将平移归零。

xform 做值的事情,但在绝对世界空间值中。

【讨论】:

    猜你喜欢
    • 2011-01-26
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 2016-01-24
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    相关资源
    最近更新 更多