每张订单都带着饮料、杯型和价格,三个函数把它们分开传来传去。类可以让一个对象把它们装在一起。这个对象应该能为自己做什么?
类(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 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。