1. ホーム
  2. python

[解決済み] Python ベクトルクラス

2022-02-08 03:05:48

質問

私はC#のバックグラウンドを持ち、このようなことはとても簡単なのですが、MayaのためにPythonに翻訳しようと思っています。

もっといい方法があるはずだ。基本的に、私は単純にx、y、z座標を持つVectorクラスを作りたいと思っていますが、このクラスが3つの座標すべてを持つタプルを返し、x、y、zプロパティを通してこのタプルの値を編集できれば、何らかの形で理想的です。

これは今のところ私が持っているものですが、そこには は、exec文を使うよりも良い方法ですよね?私はexec文を使うのが嫌いです。

class Vector(object):
    '''Creates a Maya vector/triple, having x, y and z coordinates as float values'''

    def __init__(self, x=0, y=0, z=0):
        self.x, self.y, self.z = x, y, z

    def attrsetter(attr):
        def set_float(self, value):
            setattr(self, attr, float(value))
        return set_float

    for xyz in 'xyz':
        exec("%s = property(fget=attrgetter('_%s'), fset=attrsetter('_%s'))" % (xyz, xyz, xyz))

解決方法は?

編集する。 私の回答のあるコードを@unutbuさんのオリジナルからもう少し修正し、簡略化して何が行われているのかを明確にしました。最新版では @staticmethod は完全に削除され、ネストされたワンライナーに置き換えられています。外側の関数とネストしたクラスは、名前を変更しました。 AutoFloatProperties_AutoFloatProperties のように、割り当てられた値を浮動小数点に変換して保存するという特殊な挙動を反映させることができます。それでも、メタクラスの代わりにクラス・デコレータを使った @unutbu さん自身の修正回答は、内部と使い方が非常に似ているものの、若干シンプルな解決策です。

def AutoFloatProperties(*props):
    '''metaclass'''
    class _AutoFloatProperties(type):
        # Inspired by autoprop (http://www.python.org/download/releases/2.2.3/descrintro/#metaclass_examples)
        def __init__(cls, name, bases, cdict):
            super(_AutoFloatProperties, cls).__init__(name, bases, cdict)
            for attr in props:
                def fget(self, _attr='_'+attr): return getattr(self, _attr)
                def fset(self, value, _attr='_'+attr): setattr(self, _attr, float(value))
                setattr(cls, attr, property(fget, fset))
    return _AutoFloatProperties

class Vector(object):
    '''Creates a Maya vector/triple, having x, y and z coordinates as float values'''
    __metaclass__ = AutoFloatProperties('x','y','z')
    def __init__(self, x=0, y=0, z=0):
        self.x, self.y, self.z = x, y, z # values converted to float via properties

if __name__=='__main__':
    v=Vector(1,2,3)
    print(v.x)
    # 1.0
    v.x=4
    print(v.x)
    # 4.0