編集:私の以前の回答は、一般的な使用を望んでいた一般化された AutoProperties メタクラスを作成しようとしました。@martineauの回答が示すように、Vectorクラスに特化したソリューションは物事をより簡単にすることができます。
これらの方針に沿った別のアイデアを次に示します (一般化された複雑さに対する特殊化された単純さ)。クラスデコレータ(メタクラスよりも少し理解しやすいと思います)と、デフォルト値でゲッターとセッターを単純化する@martineauのアイデアを使用します。
def AutoProperties(*props):
def _AutoProperties(cls):
for attr in props:
def getter(self,_attr='_'+attr):
return getattr(self, _attr)
def setter(self, value, _attr='_'+attr):
setattr(self, _attr, float(value))
setattr(cls,attr,property(getter,setter))
return cls
return _AutoProperties
@AutoProperties('x','y','z')
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 = map(float,(x, y, z))
元の回答:
多くの同様のプロパティを定義するときに定型コードを繰り返さないようにする方法を次に示します。
私は解決策を合理的に一般化しようとしたので、この特定の状況以外の他の状況の人々にも役立つかもしれません.
使用するには、次の 2 つのことを行う必要があります。
- 置く
__metaclass__=AutoProperties(('x','y','z'))
クラスの定義の先頭に。x必要な数の属性 (例: 、y、 ) を(文字列として) リストできzます。AutoPropertiesそれらをプロパティに変換します。
- あなたのクラス、例えば
Vectorは staticmethods_auto_setterとを定義する必要があります_auto_getter。これらは 1 つの引数 (文字列としての属性名) を取り、その属性のセッターまたはゲッター関数をそれぞれ返します。
メタクラスを使用してプロパティを自動的に設定するというアイデアは、プロパティとメタクラスに関する Guido Rossum のエッセイから来ています。そこで彼は、autoprop私が以下で使用するものと同様のメタクラスを定義しています。主な違いは、ゲッターとセッターを手動で定義するのではなく、ユーザーがゲッターとセッターのファクトリAutoPropertiesを定義することを期待していることです。
def AutoProperties(props):
class _AutoProperties(type):
# Inspired by autoprop (http://www.python.org/download/releases/2.2.3/descrintro/)
def __init__(cls, name, bases, cdict):
super(_AutoProperties, cls).__init__(name, bases, cdict)
for attr in props:
fget=cls._auto_getter(attr)
fset=cls._auto_setter(attr)
setattr(cls,attr,property(fget,fset))
return _AutoProperties
class Vector(object):
'''Creates a Maya vector/triple, having x, y and z coordinates as float values'''
__metaclass__=AutoProperties(('x','y','z'))
def __init__(self, x=0, y=0, z=0):
# I assume you want the initial values to be converted to floats too.
self._x, self._y, self._z = map(float,(x, y, z))
@staticmethod
def _auto_setter(attr):
def set_float(self, value):
setattr(self, '_'+attr, float(value))
return set_float
@staticmethod
def _auto_getter(attr):
def get_float(self):
return getattr(self, '_'+attr)
return get_float
if __name__=='__main__':
v=Vector(1,2,3)
print(v.x)
# 1.0
v.x=4
print(v.x)
# 4.0