4

これは以前にカバーされたことを知っており、おそらくクラスを構築する最もpythonicな方法ではありませんが、ノードデータを取得/設定するための多くの@プロパティを持つさまざまなMayaノードクラスがたくさんあり、見たいです手続き的に属性を構築すると、オーバーヘッド/マンチネンスが削減されます。

標準の動作が維持されるように __setattr__ を再実装する必要がありますが、特定の特殊な属性については、値が外部オブジェクトに取得/設定されます。

スタック オーバーフローで __setattr__ を再実装する例を見てきましたが、何かが足りないようです。

setAttrのデフォルト機能を維持しているとは思わない

次に例を示します。

externalData = {'translateX':1.0,'translateY':1.0,'translateZ':1.0}
attrKeys = ['translateX','translateY','translateZ']


class Transform(object):

    def __getattribute__(self, name):
        print 'Getting --->', name
        if name in attrKeys:
            return externalData[name]
        else:
            raise AttributeError("No attribute named [%s]" %name)

    def __setattr__(self, name, value):
        print 'Setting --->', name
        super(Transform, self).__setattr__(name, value)
        if name in attrKeys:
            externalData[name] = value


myInstance = Transform()
myInstance.translateX
# Result: 1.0 # 
myInstance.translateX = 9999
myInstance.translateX
# Result: 9999 # 
myInstance.name = 'myName'
myInstance.name
# AttributeError: No attribute named [name] #

!

4

4 に答える 4

3

これは私のために働いた:

class Transform(object):

    def __getattribute__(self, name):
       if name in attrKeys:
           return externalData[name]
       return super(Transform, self).__getattribute__(name)

    def __setattr__(self, name, value):
        if name in attrKeys:
            externalData[name] = value
        else:
            super(Transform, self).__setattr__(name, value)

ただし、これが良いルートかどうかはわかりません。

外部操作に時間がかかる場合 (たとえば、データベースや構成ファイルへのアクセスを偽装するためにこれを使用している場合)、コードのユーザーにコストについて間違った印象を与える可能性があります。このような場合、メソッドを使用して、ユーザーがデータを見るだけでなく、アクションを開始していることを理解できるようにする必要があります。

OTOH アクセスが速い場合は、クラスのカプセル化が壊れていないことに注意してください。Maya シーン データを取得するためにこれを実行している場合 (pymel スタイル、またはこの例のように) 時間コストとデータの安定性が多かれ少なかれ保証されているため、大したことではありません。ただし、投稿したコード例のシナリオは避けたいと思います。「translateX」を特定の値に設定すると、そのままの状態が続くと想定するのは非常に簡単です。実際には、の内容を変更する方法はたくさんあります外部変数が台無しになり、クラスの使用中に不変条件を知ることができなくなる可能性があります。クラスが使い捨ての使用を意図している場合 (たとえば、他の操作が実行されていないループとして内部で多くの高速反復処理を実行するための構文糖衣)、それを回避できますが、そうでない場合は、データをインスタンスに内部化します。

最後にもう 1 つ問題があります。「たくさんのクラス」がある場合、これを機能させるには多くのボイラープレートも実行する必要があります。Maya シーン データをラップしようとしている場合は、ディスクリプタを読んでください ( 5 分間のすばらしいビデオです)。たとえば、次のように、一般的な変換プロパティをラップできます。

import maya.cmds as cmds

class MayaProperty(object):
    '''
    in a real implmentation you'd want to support different value types, 
    etc by storing flags appropriate to different commands.... 
    '''
    def __init__(self, cmd, flag):
        self.Command = cmd
        self.Flag = flag

    def __get__(self, obj, objtype):
            return self.Command(obj, **{'q':True, self.Flag:True} )

    def __set__(self, obj, value):
        self.Command(obj, **{ self.Flag:value})

class XformWrapper(object):

    def __init__(self, obj):
        self.Object = obj

    def __repr__(self):
        return self.Object # so that the command will work on the string name of the object

    translation = MayaProperty(cmds.xform, 'translation')
    rotation = MayaProperty(cmds.xform, 'rotation')
    scale = MayaProperty(cmds.xform, 'scale')

実際のコードでは、エラー処理とよりクリーンな構成が必要ですが、アイデアがわかります。

上記のリンクの例では、構成するプロパティ記述子が多数ある場合にメタクラスを使用してクラスにデータを入力する方法について説明しています。これは、すべてのボイラープレートについて心配したくない場合に適した方法です (ただし、起動時間のわずかなペナルティがあります)。 - それが悪名高い Pymel スタートアップ クロールの理由の 1 つだと思います...)

于 2014-03-10T05:53:52.217 に答える
0

ここにあなたのスニペットがあります:

class Transform(object):

    def __getattribute__(self, name):
        print 'Getting --->', name
        if name in attrKeys:
            return externalData[name]
        else:
            raise AttributeError("No attribute named [%s]" %name)

    def __setattr__(self, name, value):
        print 'Setting --->', name
        super(Transform, self).__setattr__(name, value)
        if name in attrKeys:
            externalData[name] = value

__setattr__()呼び出したときにが にないためmyInstance.name = 'myName'、externalData ディクショナリには挿入されませんが、に追加されます。nameattrKeysself.__dict__['name'] = value

したがって、その特定の名前を検索しようとすると、externalData辞書を調べていないため__getattribute__、例外が発生します。

__getattribute__以下のように、例外変更を発生させる代わりに を変更することで、これを修正できます。

def __getattribute__(self, name):
    print 'Getting --->', name
    if name in attrKeys:
        return externalData[name]
    else:
        return object.__getattribute__(self, name)
于 2014-03-10T05:08:38.507 に答える