是否可以为python中的多个类属性定义通用的setter方法?

问题描述

我有一个自定义类,其实例用几个属性foo,bar,...初始化,这些属性是数字值或字符串。几种类方法使用这些属性来计算类实例的其他属性。我想将这些属性定义为属性,以便在更改它们时会重新计算其他属性。以下作品:

class MyClass:

    def __init__(self,foo,bar):
        self._foo = foo
        self._bar = bar


    @property
    def foo(self):
        return self._foo
    @foo.setter
    def foo(self,new_foo):
       old_foo = self._foo:
        self._foo = new_foo
        if old_foo != new_foo:
            self._force_recalc()

    @property
    def bar(self):
        return self._bar
    @bar.setter
    def bar(self,new_bar):
        old_bar = self._bar:
        self._bar = new_bar
        if old_bar != new_bar:
            self._force_recalc()

    def _force_recalc(self)
    # call some methods that recalculate attributes

但是,有两个方面让我感到震惊:

  • setter方法基本上是复制粘贴,只调整了变量名。但是我无法提出一种使用通用设置方法的解决方案。
  • 是否有避免old_fooold_bar的方法?它们是由于_force_recalc必须在 foobar重设之后被调用,但前提是它们的值必须更改。

解决方法

我首先尝试了@Barmar建议的解决方案。这是可行的,但是会导致在初始化所有属性期间出现不必要的重新计算量的问题。另外,它们仍然必须单独定义,我无法检查该值是否实际更改。

按照@ juanpa.arrivillaga的建议,我定义了自己的装饰器类,最终得到了这样的内容:

class MyClass:

    class _MyProperty:
        def __init__(self,value=None):
            self.value = value
        def __get__(self,instance,owner=None):
            return self.value
        def __set__(self,value):
            if value != self.value:
                self.value = value
                instance._force_recalc()

    @classmethod
    def _set_init_state(cls,values):
        cls.foo,cls.bar = [cls._MyProperty(value) for value in values]


    def __init__(self,foo,bar):
        self._set_init_state((foo,bar))
        self._force_recalc()


    def _force_recalc(self)
    # call some methods that recalculate attributes

虽然这看起来似乎不太重复,但可以说前者更为明确。但是,我喜欢它,它可以解决我的原始要求。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...