Python面向对象编程第19篇 只读属性

Posted 不剪发的Tony老师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python面向对象编程第19篇 只读属性相关的知识,希望对你有一定的参考价值。

本文我们介绍如何定义 Python 只读属性,以及使用只读属性定义计算属性。

只读属性简介

定义只读属性的方法就是创建只有 getter 方法的属性。不过,这种方法定义的不是真正意义上的只读属性,因为我们总是可以访问和修改底层的属性。

只读属性通常用于某些特定场景,例如定义计算属性。

以下示例定义了一个类 Circle,包含 radius 属性和 area() 方法:

import math


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

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

下面的代码创建了一个新的 Circle 对象,并且返回了它的面积:

c = Circle(10)
print(c.area())

输出结果如下:

314.1592653589793

以上代码可以正常运行。但是,如果 area 是 Circle 对象的一个属性,而不是方法的话,会更加符合我们的常识。为了将 area() 方法修改为属性,可以使用 @property 装饰器:

import math


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

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


c = Circle(10)
print(c.area)

area 基于 radius 属性的计算结果,因此通常被称为计算属性。

缓存计算属性

假如我们创建了一个新的 Circle 对象,并且多次访问 area 属性。每次访问时,都需要重新计算面积,这种方式不够高效。

为了提高性能,我们只需要在半径发生变化时重新计算圆的面积。如果半径没有改变,我们可以重用之前的面积。为此,我们可以使用以下缓存技术:

  • 首先,计算面积并将其缓存。
  • 然后,当半径发生改变时重新计算面积;否则直接从缓存中返回面积。

以下代码重新定义了 Circle 类,对 area 属性进行了缓存处理:

import math


class Circle:
    def __init__(self, radius):
        self._radius = radius
        self._area = None

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError('Radius must be positive')

        if value != self._radius:
            self._radius = value
            self._area = None

    @property
    def area(self):
        if self._area is None:
            self._area = math.pi * self.radius ** 2

        return self._area

首先,在 __init__ 方法中将 _area 设置为 None。_area 属性就是存储面积的缓存。

其次,如果半径发生变化(通过 setter 方法),将 _area 重置为 None。

最后,定义计算属性 area。如果 _area 不为 None,返回它的值;否则,计算面积并将其保存到 _area,返回数据。

总结

  • 通过只定义 getter 方法的方式创建只读属性。
  • 使用计算属性创建更加自然的类属性。
  • 使用缓存改进计算属性的性能。

以上是关于Python面向对象编程第19篇 只读属性的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象编程第18篇 属性装饰器

Python面向对象编程第20篇 删除属性

Python面向对象编程第20篇 删除属性

Python面向对象编程第18篇 属性装饰器

Python面向对象编程第01篇 OOP简介

Python面向对象编程第01篇 OOP简介