如何在Python中添加多个类似属性
我正在构建一个模拟器,它将模拟各种类型的实体。所以我有一个基类,如何在Python中添加多个类似属性,python,properties,descriptor,Python,Properties,Descriptor,我正在构建一个模拟器,它将模拟各种类型的实体。所以我有一个基类,ModelObject,并将为所有不同的实体使用子类。每个实体都有一组我想要跟踪的属性,因此我还得到了一个名为RecordedDetail的类,它跟踪更改(基本上构建了一个(时间步长,值)对的列表),每个ModelObject都有一个dict来存储这些更改。所以我得到了,有效的 class ModelObject(object): def __init__(self): self.details = {}
ModelObject
,并将为所有不同的实体使用子类。每个实体都有一组我想要跟踪的属性,因此我还得到了一个名为RecordedDetail
的类,它跟踪更改(基本上构建了一个(时间步长,值)对的列表),每个ModelObject
都有一个dict
来存储这些更改。所以我得到了,有效的
class ModelObject(object):
def __init__(self):
self.details = {}
self.time_step = 0
def get_detail(self, d_name):
""" get the current value of the specified RecordedDetail"""
return self.details[d_name].current_value()
def set_detail(self, d_name, value):
""" set the current value of the specified RecordedDetail"""
self.details[d_name].set_value(value, self.time_step)
class Widget(ModelObject):
def __init__(self):
super().__init__(self)
self.details["level"] = RecordedDetail()
self.details["angle"] = RecordedDetail()
@property
def level(self):
return self.get_detail("level")
@level.setter
def level(self, value):
self.set_detail("level", value)
@property
def angle(self):
return self.get_detail("angle")
@angle.setter
def angle(self):
self.set_detail("angle", value)
这会变得非常重复,我忍不住想,一定有一种方法可以使用描述符来实现自动化,但我不知道如何实现。我最终得到了
class RecordedProperty(object):
def __init__(self, p_name):
self.p_name = p_name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.get_detail(self.p_name)
def __set__(self, instance, value):
instance.set_detail(self.p_name, value)
class Widget(ModelObject):
level = RecordedProperty("level")
angle = RecordedProperty("angle")
def __init__(self):
super().__init__(self)
self.details["level"] = RecordedDetail()
self.details["angle"] = RecordedDetail()
这是一个小小的进步,但仍然需要大量的打字
所以,有几个问题
\uuuuuu get\uuuuuu
,\uuuu set\uuuuuu
等)添加到RecordedDetail
类中?这样做有什么好处吗代码的最后一位在正确的轨道上。通过使用元类为列表中的每个项创建一个命名的RecordedProperty和一个匹配的RecordedDetail,您可以减少这个过程的麻烦。下面是一个简单的例子:
class WidgetMeta(type):
def __new__(cls, name, parents, kwargs):
'''
Automate the creation of the class
'''
for item in kwargs['_ATTRIBS']:
kwargs[item] = RecordedProperty(item)
return super(WidgetMeta, cls).__new__(cls, name, parents, kwargs)
class Widget(ModelObject):
_ATTRIBS = ['level', 'angle']
__metaclass__ = WidgetMeta
def __init__(self, *args, **kwargs):
super().__init__(self)
self.Details = {}
for detail in self._ATTRIBS:
self.Details[detail] = RecordedDetail()
子类只需要在\u ATTRIBS
中有不同的数据
另一种选择是(我认为它更复杂),您可以使用元类来定制init,就像定制new一样,从_ATTRIBS列表中创建RecordedDetails
第三种选择是在第一次访问时在每个实例中创建RecordedDetail。只要您的代码没有要求每个属性都有一个RecordedDetail,即使没有触及RecordedDetail,也可以这样做
警告我对蟒蛇3不太熟悉;我经常在2.7x中使用上述模式