面向对象编程时定义属性需要注意:有些属性是初始化实例时根据参数来定,而有些属性可根据其它属性推导,注意不要把这种可推导的属性把__init__函数中。正确的做法是将可推导的属性定义成函数,另通过@property将函数伪装成属性。
案例,定义圆形类,该圆形有半径、周长、面积这3个属性。
错误的案例
class Circle(): # 定义圆形对象
def __init__(self, radius): # 实例初始化时需要参数——半径
self.radius = radius
self.perimeter = 2*3.1415926535*self.radius
self.area = 3.1415926535*self.radius**2
a_Circle = Circle(5)
print(
f'圆的半径是{a_Circle.radius},它的面积是{a_Circle.area:.2f},它的周长是{a_Circle.perimeter:.2f}')
a_Circle.radius = 10
print(
f'圆的半径是{a_Circle.radius},它的面积是{a_Circle.area:.2f},它的周长是{a_Circle.perimeter:.2f}')
out:
圆的半径是5,它的面积是78.54,它的周长是31.42
圆的半径是10,它的面积是78.54,它的周长是31.42
在上述案例中定义了一个圆形类,它有半径、周长、面积3个属性,定义的时候好像没有问题,可是初始化以后会发现问题。
圆的半径是5时,打印它的半径、面积、周长时毫无问题,但是改变当改变该圆的半径值时,面积和周长并未更新!
正确的案例
class Circle(): # 定义圆形对象
def __init__(self, radius): # 实例初始化时需要参数——半径
self.radius = radius
@property
def perimeter(self): # 圆的周长
return 2*3.1415926535*self.radius
@property
def area(self): # 圆的半径
return 3.1415926535*self.radius**2
a_Circle = Circle(5)
print(
f'圆的半径是{a_Circle.radius},它的面积是{a_Circle.area:.2f},它的周长是{a_Circle.perimeter:.2f}')
a_Circle.radius = 10
print(
f'圆的半径是{a_Circle.radius},它的面积是{a_Circle.area:.2f},它的周长是{a_Circle.perimeter:.2f}')
out:
圆的半径是5,它的面积是78.54,它的周长是31.42
圆的半径是10,它的面积是314.16,它的周长是62.83
在上述案例中定义了一个圆形类,它有半径一个属性,周长和面积是根据半径计算出结果的函数,在函数前加@property可将函数伪装成属性。
圆的半径是5时,打印它的半径、面积、周长时毫无问题;改变当改变该圆的半径值时,面积和周长同步更新!