如何在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中使用上述模式