类变量不更新

时间:2018-03-26 19:01:36

标签: python class python-3.6

我有以下基本课程涉及一个圆圈。我的问题是,当我用c.diameter(10)直接更新直径时,为什么半径更新为5?如输出所示,它仍然是4:

from math import pi


class Circle:
    def __init__(self, radius=1):
        self.radius = radius
        self.diameter = self.radius * 2

    def diameter(self, diameter):
        self.diameter = diameter
        self.radius = self.diameter / 2
        return self.radius, self.diameter

    def area(self):
        return self.radius ** 2 * pi


c = Circle(3)
print("c.radius:", c.radius)
print("c.area():", c.area())
c.radius = 4  # change radius
print("c.radius:", c.radius)
print("c.area():", c.area())
c.diameter = 10  # change diameter
print("c.diameter:", c.diameter)
print("c.radius:", c.radius)

输出:

c.radius: 3
c.area(): 28.274333882308138
c.radius: 4
c.area(): 50.26548245743669
c.diameter: 10
c.radius: 4   <--- Radius should be 5, since the Radius is Diameter / 2

2 个答案:

答案 0 :(得分:0)

您有两件名为diameter的东西:

  • 实例上的一个属性,在self.diameter中设置为__init__,之后设置为c.diameter = 10
  • 名为diameter的类的方法。永远不会访问此方法。您无法在实例上访问它,因为diameter属性掩盖方法。

在Python类中,方法仍然只是属性。 c.area返回方法对象,只有c.area()实际调用该方法。

因此,仅引用c.diameter实际上不会为您提供方法,它会为您提供实例上的属性,它只是一个整数对象。

您有两种选择:

  • 将方法重命名为set_diameter(),例如。
  • diameter属性设为property object。属性与属性一样使用,但在实例上获取或设置属性会触发要调用的方法。

后一个选项是'pythonic'选项,Python开发人员会使用的方法:

class Circle:
    def __init__(self, radius=1):
        self.radius = radius

    @property
    def diameter(self):
        return self.radius * 2

    @diameter.setter
    def diameter(self, value):
        self.radius = value / 2

    def area(self):
        return self.radius ** 2 * pi

@property / @diameter.setter装饰器对定义属性的getter和setter;每当您想要读取获取)属性的值时,就会调用第一个def diameter,而当写>>> c = Circle(3) >>> c.diameter 6 >>> c.diameter = 4 >>> c.radius 2.0 >>> c.diameter 4.0 >当您尝试分配新值( setter )时调用:

diameter

请注意,我们从未在setter中设置名为c.diameter的属性!相反,当您访问diameter进行阅读时,始终会计算该值。

您还会注意到,当您为float属性分配一个整数时,半径变为/值;那是因为//运算符总是产生一个浮点值,即使对于整数输入也是如此。如果你总是必须有一个整数,请使用from math import pi class Circle: def __init__(self, radius=1): self._radius = radius self._diameter = radius * 2 @property def diameter(self): return self._diameter @diameter.setter def diameter(self, diameter): self._diameter = diameter self._radius = diameter / 2 @property def radius(self): return self._radius @radius.setter def radius(self, radius): self._radius = radius self._diameter = radius * 2 def area(self): return self.radius ** 2 * pi if __name__ == "__main__": c = Circle(3) print("c.radius:", c.radius) print("c.area():", c.area()) c.radius = 4 # change radius print("c.radius:", c.radius) print("c.area():", c.area()) c.diameter = 10 # change diameter print("c.diameter:", c.diameter) print("c.radius:", c.radius) (分区)。

答案 1 :(得分:0)

一种方法是使用具有相应设置器的属性来确保更新内部数据:

这样的事情:

// Replace x with just under your max size.
const int kBufferSize = x * 1024 * 1024;  // x MB