🎯 本章你会学到:class、self、继承、dataclass:够用就好的面向对象。建议边读边敲,每节练习先自己做,再展开答案对照。
Python 的面向对象比 Java 轻:没有接口关键字、没有访问修饰符(靠下划线约定)、方法第一个参数永远是 self。写小东西时,一个 dataclass 往往就够了。
类、属性与方法
dataclass
from dataclasses import dataclass
@dataclass
class Student:
name: str
score: int = 0
def passed(self):
return self.score >= 60
s = Student("Ann", 90)
print(s)
print(s.passed(), Student("Bob").passed())运行结果
Student(name='Ann', score=90)
True False
self必须在每个实例方法里显式写在第一个参数位置。@dataclass自动生成__init__、__repr__、__eq__,装数据的类首选。_name表示“内部使用”(约定,不是强制);__name会触发名称改写。@property可以把方法变成属性访问,用于计算字段与校验。
继承与方法重写
继承与多态
class Shape:
def area(self):
raise NotImplementedError
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return 3.14159265 * self.r ** 2
class Square(Shape):
def __init__(self, side):
self.side = float(side)
def area(self):
return self.side ** 2
shapes = [Circle(1), Square(2)]
print(f"{sum(s.area() for s in shapes):.2f}")
print([round(s.area(), 2) for s in shapes])运行结果
7.14
[3.14, 4.0]
父类 Shape 的 area 抛 NotImplementedError,子类各自实现。遍历 shapes 时调用 s.area() 会自动选到对应实现——这就是多态,和 Java 的写法几乎一样,只是不需要接口声明。
⚠️ 易错点 类属性是所有实例共享的;把可变对象写成类属性(如
items = [])会导致所有实例互相污染,应该放在 __init__ 里。⚠️ 易错点
__init__ 不是“构造函数”而是初始化方法;真正的构造由 __new__ 完成——日常只需要关注 __init__。✍️ 本节练习
7.1必做矩形类
写一个 Rectangle 类(宽、高),提供 area() 和 perimeter() 方法;读入宽高输出面积与周长(2 位小数)。
输入 一行两个实数:宽 高。
输出 两行:area=、perimeter=(2 位小数)。
样例输入
3 4样例输出
area=12.00
perimeter=14.00💡 提示 构造器里存 self.width、self.height,两个方法返回计算值。
✅ 查看参考答案与解析
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
w, h = map(float, input().split())
r = Rectangle(w, h)
print(f"area={r.area():.2f}")
print(f"perimeter={r.perimeter():.2f}")解析 用 map(float, input().split()) 一次读入两个浮点数,然后直接构造对象。
7.2挑战银行账户(异常驱动)
写 BankAccount 类(余额、deposit、withdraw)。取款超过余额时抛 ValueError。读入初始余额和若干操作,越界取款输出 error: insufficient funds,最后输出余额(2 位小数)。
输入 第一行初始余额;第二行操作数 n;接下来 n 行 + 金额 或 - 金额。
输出 越界时输出错误行;最后一行 balance=余额。
样例输入
100
3
+ 50
- 30
- 500样例输出
error: insufficient funds
balance=120.00💡 提示 在类里判断并 raise ValueError("insufficient funds"),调用处 try/except 打印。
✅ 查看参考答案与解析
class BankAccount:
def __init__(self, balance=0.0):
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("insufficient funds")
self.balance -= amount
account = BankAccount(float(input()))
for _ in range(int(input())):
op, amount = input().split()
try:
if op == "+":
account.deposit(float(amount))
else:
account.withdraw(float(amount))
except ValueError as e:
print(f"error: {e}")
print(f"balance={account.balance:.2f}")解析 把“能不能取”这条规则放进类里,调用方只负责捕获——这就是把业务规则封装在对象内部的写法。