Python面向对象编程第09篇 再谈类变量

Posted 不剪发的Tony老师

tags:

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

本篇我们继续学习 Python 类属性(变量)以及使用场景,类变量的基本概念可以参考第 3 篇

类属性简介

以下是一个简单的 Circle 类:

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

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

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

Circle 类拥有两个属性 pi 和 radius,以及两个计算圆的面积和周长的方法。

pi 和 radius 都是实例属性。也就是说,它们属于 Circle 类的具体实例。如果我们改变了某个实例的属性,不会影响其他实例。

除了实例属性之外,Python 还支持类属性。类属性不属于任何具体实例,它们由类的所有实例共享。

类属性和 Java 以及 C# 语言中的静态方法类似,但不完全相同。

类属性的定义位于 __init__() 方法之外。例如,以下示例定义了类属性 pi:

class Circle:
    pi = 3.14159

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

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

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

我们可以通过类的实例或者类名访问类属性:

object_name.class_attribute
class_name.class_attribute

area() 和 circumference() 方法通过 self 变量访问了类属性 pi。

在 Circle 类外部,我们可以通过类的实例或者直接通过类访问类属性 pi,例如:

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

输出结果如下:

3.14159
3.14159

类属性的原理

当我们通过类的实例访问属性时,Python 首先会在实例的属性列表中查找属性,然后继续在类的属性列表中查找属性。一旦在实例的属性列表或者类的属性列表中找到了相应的属性,Python 会立即返回属性的值。

但是,如果我们直接通过类访问属性,Python 直接在类的属性列表中查找属性。以下示例定义了一个 Test 类,演示了 Python 如何处理实例属性和类属性:

class Test:
    x = 10

    def __init__(self):
        self.x = 20


test = Test()
print(test.x)  # 20
print(Test.x)  # 10

Test 类拥有两个同名的属性 x,其中一个是实例属性,另一个是类属性。当我们同实例访问属性 x 时,返回的是实例属性的值(20)。当我们通过 Test 类访问属性 x 时,返回的是类属性的值(10)。

类属性应用场景

类属性的实用场景包括存储类常量、跨实例的数据跟踪以及定义默认值。

存储类常量

常量不会随着实例的不同而改变,因此非常适合使用类属性存储。

例如, Circle 类拥有一个常量 pi,它的值对所有实例都相同。因此,我们可以将 pi 定义为一个类属性。

跨实例数据跟踪

以下示例为 Circle 类增加了一个类属性 circle_list。当我们创建一个新的 Circle 类实例时,构造函数会将该实例增加到列表中:

class Circle:
    circle_list = []
    pi = 3.14159

    def __init__(self, radius):
        self.radius = radius
        # add the instance to the circle list
        self.circle_list.append(self)

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

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


c1 = Circle(10)
c2 = Circle(20)

print(len(Circle.circle_list))  # 2

定义默认值

有时候我们想要为类的所有实例设置一个默认值,就可以利用类属性实现。

以下示例定义了一个 Product 类,它的所有实例都会拥有一个默认的折扣率 default_discount:

class Product:
    default_discount = 0

    def __init__(self, price):
        self.price = price
        self.discount = Product.default_discount

    def set_discount(self, discount):
        self.discount = discount

    def net_price(self):
        return self.price * (1 - self.discount)


p1 = Product(100)
print(p1.net_price())
100

p2 = Product(200)
p2.set_discount(0.05)
print(p2.net_price())
190

总结

  • 类属性由类的所有实例共享。类属性的定义位于 __init__() 方法之外。
  • 通过 class_name.class_attribute 或者 object_name.class_attribute 访问类属性 class_attribute 的值。
  • 类属性可以用于存储类常量、实现跨实例的数据跟踪以及定义默认值。

以上是关于Python面向对象编程第09篇 再谈类变量的主要内容,如果未能解决你的问题,请参考以下文章

再谈类与对象

再谈类和对象

Python面向对象编程第06篇 实例变量

Python面向对象编程第06篇 实例变量

Python面向对象编程第03篇 类变量

Python面向对象编程第03篇 类变量