【问题标题】:Multiple properties with similar getter/setter functions?具有类似 getter/setter 函数的多个属性?
【发布时间】:2018-04-17 22:30:19
【问题描述】:

定义具有大量属性的类的最简洁方法是什么,每个属性都调用具有不同参数的相同 setter 函数?

以下是我想要实现的目标。三个属性(red_LED 等)中的每一个都在设置时调用相同的 TalkToHardware() 函数,但地址不同。如您所见,这是可行的,但类定义又长又笨重。它也容易出错。

class Hardware_Controller(object):

    def __init__(self):
        self.red_LED_address = 0
        self.blue_LED_address = 1
        self.green_LED_address = 2

    @property
    def red_LED(self):
        return self._red_LED_status

    @red_LED.setter
    def red_LED(self,value):
        self.TalkToHardware(self.red_LED_address,value)
        self._red_LED_status = value

    @property
    def blue_LED(self):
        return self._red_LED_status

    @blue_LED.setter
    def blue_LED(self,value):
        self.TalkToHardware(self.blue_LED_address,value)
        self._blue_LED_status = value

    @property
    def green_LED(self):
        return self._red_LED_status

    @green_LED.setter
    def green_LED(self,value):
        self.TalkToHardware(self.green_LED_address,value)
        self._green_LED_status = value

    def TalkToHardware(self,address,value):
        print('Sending %i to address %i' % (value,address))

if __name__ == "__main__":
    a = Hardware_Controller()
    a.red_LED = 1
    a.green_LED = 0
    print(a.red_LED)

输出:

Sending 1 to address 0
Sending 0 to address 2
1

我希望类定义看起来更像这样:

class Hardware_Controller(object):

    def __init__(self):
        self.red_LED_address = 0
        self.blue_LED_address = 1
        self.green_LED_address = 2

        self.red_LED = some_magic(self.red_LED_address)
        self.blue_LED = some_magic(self.blue_LED_address)
        self.green_LED = some_magic(self.green_LED_address)

    def some_magic(address):
        # Do magic things
        pass

是否有一种干净的方法来完成此操作,仍然能够直接访问每个 LED,如第一个示例的主要功能所示?

【问题讨论】:

  • property 只是一个描述符工厂,请参阅docs.python.org/3/howto/descriptor.html 了解如何编写它们。
  • 您能澄清一下您要做什么吗? 'some_magic' 返回一个函数吗?没有描述 some_magic 应该做什么
  • @JayFresco some_magic 将 self.red_LED 初始化为与第一个示例中的 self.red_LED 具有相同行为的对象。

标签: python properties


【解决方案1】:

您可以创建一个函数来简单地定义并返回所需的property 类实例,然后使用它来定义类,从而摆脱所有重复的代码

(如果不明显,下面代码中的 LED_property() 函数对应于您问题中名为 some_magic() 的函数。)

class Hardware_Controller(object):
    def LED_property(color_name):
        """ Create and return a property for the given color_name. """
        address_name = color_name + '_LED_address'
        storage_name = '_' + color_name + '_LED_status'

        @property
        def prop(self):
            return getattr(self, storage_name)

        @prop.setter
        def prop(self, value):
            address = getattr(self, address_name)
            self.TalkToHardware(address, value)
            setattr(self, storage_name, value)

        return prop

    red_LED = LED_property('red')
    blue_LED = LED_property('blue')
    green_LED = LED_property('green')

    def __init__(self):
        self.red_LED_address = 0
        self.blue_LED_address = 1
        self.green_LED_address = 2

    def TalkToHardware(self, address, value):
        print('Sending %i to address %i' % (value, address))

    del LED_property  # Function isn't needed outside class definition.


if __name__ == "__main__":
    a = Hardware_Controller()
    a.red_LED = 1     # -> Sending 1 to address 0
    a.green_LED = 0   # -> Sending 0 to address 2
    print(a.red_LED)  # -> 1

类似于 David Beazley 和 Brian Jones(2013 年)的 Python Cookbook,第三版 中的“9.21 避免重复属性方法”。我在第 382 页找到了entire book (8.8 Mb) 的 PDF。

【讨论】:

  • 这是我的设想,我明天试试。
【解决方案2】:

也许你可以这样做:

def setter(self, address, value):
    if address == self.red_LED_address:
        attr = '_red_LED_status'
    if address == self.blue_LED_address:
        attr = '_blue_LED_status'
    if address == self.green_LED_address:
        attr = '_green_LED_status'
    self.TalkToHardware(address, value)
    setattr(self, attr, value) ## does this: self._XXX_LED_address = value

这是所有 LED 设置器功能的包罗万象的功能。

希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    相关资源
    最近更新 更多