第 15 课 · 入门 · 19 分钟

Python 类与对象

把数据和操作数据的函数组合成一个可复用的小对象。

类定义__init__ 与 self方法与实例

每张订单都带着饮料、杯型和价格,三个函数把它们分开传来传去。类可以让一个对象把它们装在一起。这个对象应该能为自己做什么?

类(class)是创建对象的蓝图。对象用属性保存数据,用方法提供行为。先从订单这样的小记录开始,一次只加一个方法。 你还会区分类属性与实例属性、在 __init__ 中守住不变量,并写出有用的 __repr__。

定义类

class 关键字创建蓝图。创建新对象时会运行 __init__。self 指向当前这个对象,属性通过 self.name 赋值。

class Order:
    def __init__(self, drink, price):
        self.drink = drink
        self.price = price

order = Order("latte", 4.5)
print(order.drink)
print(order.price)

一个小类

添加方法

方法就是定义在类里的函数,第一个参数是 self。它可以读取对象属性并返回结果;调用时不需要手动传入 self。

class Order:
    def __init__(self, drink, price, quantity=1):
        self.drink = drink
        self.price = price
        self.quantity = quantity

    def total(self):
        return self.price * self.quantity

print(Order("latte", 4.5, 2).total())

带默认值的方法

创建独立对象

每个实例都有自己的属性值。遍历对象列表,通常比维护几个平行列表更清楚。逐个打印字段,检查每个对象保存了什么。

class Order:
    def __init__(self, drink, price):
        self.drink = drink
        self.price = price

orders = [Order("latte", 4.5), Order("tea", 3.0)]
for order in orders:
    print(order.drink, order.price)

对象列表

类属性是所有实例共享的

在类体里赋值的属性属于类,不属于某个对象。可变的类属性会被所有实例共享。每个对象自己的默认值要放进 __init__;只有确实该共享的值才留在类上。

class Order:
    tags = []

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

first = Order("latte")
second = Order("tea")
first.tags.append("gift")
print(second.tags)
print(first.tags is second.tags)

所有订单共用同一个列表

对象创建时就校验不变量

对象不应该以非法状态存在。在 __init__ 里检查价格和数量,带着坏值抛出 ValueError。调用方只需处理一个清楚的失败,而不是过很久才发现总价是负数。

class Order:
    def __init__(self, drink, price):
        if price < 0:
            raise ValueError(f"negative price: {price}")
        self.drink = drink
        self.price = price

for price in [4.5, -1]:
    try:
        order = Order("latte", price)
        print(order.drink, order.price)
    except ValueError as error:
        print(type(error).__name__, error)

在对象存在之前拒绝坏值

__repr__ 应该帮助调试

没有 __str__ 时,print(order) 会退回到 __repr__。好的 __repr__ 显示类名和能识别对象的字段。它面向开发者,所以要明确,不要写成一句营销文案。

class Order:
    def __init__(self, drink, price, quantity=1):
        self.drink = drink
        self.price = price
        self.quantity = quantity

    def __repr__(self):
        return f"Order(drink={self.drink!r}, price={self.price}, quantity={self.quantity})"

print(Order("latte", 4.5, 2))

显示类名和识别字段

本课要点

  • 类定义对象的形状。
  • __init__ 初始化新实例。
  • self 指向当前实例。
  • 方法可以读取属性并返回计算结果。
  • 可变默认值放进 __init__;类属性由所有实例共享。

常见错误

  • 定义方法时忘记写 self。
  • 只定义了类,却从未调用它创建对象。
  • 不小心让多个实例共享同一个可变属性。
  • 把类级别的列表当成每个对象自己的标签列表。
轮到你

创建带 drink 和 price 的 Order 类,再为两个订单打印格式化总价。

动手试试

改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。

浏览器内 Python本地运行 · 无需账号
首次运行会从 CDN 下载 Pyodide。修改后点击“运行代码”。

练习本课

12 道题,作答后立即看到解释。

查看 12 道题答案开始练习
← 排序与 key模块与导入 →