将@property装饰器用于Python类中的相关属性

时间:2018-06-28 09:46:05

标签: python class properties getter-setter python-decorators

此问题涉及在Python的类中使用@property装饰器。我想创建一个具有两个公共属性的类(例如a和b)。我还希望类具有进一步的公共属性(例如c),该属性始终等于基于类中其他属性(例如a + b = c)的某种计算。属性c必须是可公开获取的,但是由于对a和b的依赖,我真的不希望它可以公开获取。

下面的代码块将不会运行,因为在第3行中设置self.a时,将调用a.setter,这会引发AttributeError,因为第14行中的self.b尚未设置。

在这种情况下,使用@property装饰器正确吗?

在初始化方法期间正确设置属性a,b和c的最Python化方法是什么?理想情况下,如果可能的话,不必在一个以上的地方定义a,b和c之间的关系(即与下面的代码不同,第13和22行定义a,b和c之间的关系)?

还可以强制用户不能直接设置c的值吗,这是最Python化的方法吗?

class ExampleClass1:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, a):
        self._a = a
        self.c = self._a + self.b

    @property
    def b(self):
        return self._b

    @b.setter
    def b(self, b):
        self._b = b
        self.c = self._b + self.a

2 个答案:

答案 0 :(得分:0)

我认为您正在以错误的方式进行处理。如果您需要属性c始终是ab的总和,那么那个属性需要是一个属性:

@property
def c(self):
    return self.a + self.b

,您根本不需要ab的属性。

这也解决了使其不可设置的问题;如果您没有为c定义设置器,则不能直接设置它。

答案 1 :(得分:0)

刚看到你的帖子。

我遇到了完全相同的问题,我认为这似乎有效:

class ExampleClass1:

    def __init__(self, a, b):
        self.a = a
        self.b = b
        
    @property
    def a(self):
        return self._a
    
    @a.setter
    def a(self, value):
        self._a = value
        try:
            self.c = self._a + self.b
        except AttributeError:
            self.c = self._a
    
    @property
    def b(self):
        return self._b
    
    @b.setter
    def b(self, value):
        self._b = value
        try:
            self.c = self.a + self._b
        except AttributeError:
            self.c = self._b

当我尝试将属性装饰器用于 'c' 时,它会导致每次访问属性 'c' 时执行 'a' 和 'b' 的总和。

为了避免这种情况,我们需要按照您的建议使用 setter 方法,但我们当然会遇到该循环。 try-except 似乎胜过这一点。