Редактировать: В моем предыдущем ответе я попытался создать обобщенный метакласс 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
, необходимо определить статические методы _auto_setter
и _auto_getter
. Они принимают один аргумент, имя атрибута как строку, и возвращают функцию установки или получения, соответственно, для этого атрибута.
Идея использования метаклассов для автоматической настройки свойств взята из эссе Гвидо Россума о свойствах и метаклассах . Там он определяет метакласс 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