Python 中的类练习题
一、类的基础:定义与创建实例
练习 1.1 定义最简单的类
题目:
定义一个类 Car(汽车),要求:
__init__(self, brand, color)接收品牌和颜色,分别存成self.brand和self.color- 定义方法
info(self),打印:"我是一辆 xxx 色的 xxx"(先颜色后品牌)
创建两个实例:
car1:品牌"宝马",颜色"白"car2:品牌"奔驰",颜色"黑"
分别调用 info()。
参考答案:
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def info(self):
print(f"我是一辆{self.color}色的{self.brand}")
car1 = Car("宝马", "白")
car2 = Car("奔驰", "黑")
car1.info() # 我是一辆白色的宝马
car2.info() # 我是一辆黑色的奔驰
练习 1.2 理解 self 和形参的关系
题目:
指出下面代码中,哪些是形参,哪些是实例属性(用 self. 绑定的变量),并说明 self 在这里代表什么。
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
参考答案:
- 形参:
name、age(定义在括号里的占位参数) - 实例属性:
self.name、self.age(用self.开头,绑定在实例上的属性) - self 代表:当前正在创建的那个实例本身,Python 会在调用时自动传入,不需要手动传
练习 1.3 每个实例的属性相互独立
题目:
用下面的 Dog 类,创建 dog1 = Dog("旺财", 3) 和 dog2 = Dog("小黑", 2)。
然后把 dog1.age 改为 5,再分别打印 dog1.age 和 dog2.age,观察 dog2 是否受影响。
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
参考答案:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
dog1 = Dog("旺财", 3)
dog2 = Dog("小黑", 2)
dog1.age = 5
print(dog1.age) # 5
print(dog2.age) # 2(dog2 没有受影响)
要点: 每个实例拥有各自独立的属性副本,改一个不会影响另一个。
二、给属性指定默认值
练习 2.1 形参带默认值
题目:
定义类 Book,__init__(self, title, author, price=0) 中 price 默认为 。
创建:
b1 = Book("Python入门", "张三")(不传 price)b2 = Book("Java入门", "李四", 59)
分别打印两个实例的 title 和 price。
参考答案:
class Book:
def __init__(self, title, author, price=0):
self.title = title
self.author = author
self.price = price
b1 = Book("Python入门", "张三")
b2 = Book("Java入门", "李四", 59)
print(b1.title, b1.price) # Python入门 0
print(b2.title, b2.price) # Java入门 59
练习 2.2 在 init 里直接赋固定初始值
题目:
定义类 Player(玩家),__init__(self, name) 只接收名字,另外在 __init__ 里直接设置:
self.score = 0(初始分数)self.level = 1(初始等级)
创建 p = Player("小明"),打印 p.name、p.score、p.level。
参考答案:
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.level = 1
p = Player("小明")
print(p.name) # 小明
print(p.score) # 0
print(p.level) # 1
练习 2.3 可选属性用 None 做默认值
题目:
定义类 Person,__init__(self, name, phone=None)。
定义方法 contact(self):
- 如果
phone是None,返回"xxx 未填手机号" - 否则返回
"xxx 的手机:yyy"
创建两个实例,一个传手机号一个不传,分别打印 contact() 结果。
参考答案:
class Person:
def __init__(self, name, phone=None):
self.name = name
self.phone = phone
def contact(self):
if self.phone is None:
return f"{self.name} 未填手机号"
return f"{self.name} 的手机:{self.phone}"
p1 = Person("小明")
p2 = Person("小红", "13900000000")
print(p1.contact()) # 小明 未填手机号
print(p2.contact()) # 小红 的手机:13900000000
三、修改属性的值
练习 3.1 直接修改属性
题目:
用下面的 Player 类,创建 p = Player("小红"),先打印 p.score,然后直接把 p.score 改为 100,再次打印 p.score。
class Player:
def __init__(self, name):
self.name = name
self.score = 0
参考答案:
class Player:
def __init__(self, name):
self.name = name
self.score = 0
p = Player("小红")
print(p.score) # 0
p.score = 100
print(p.score) # 100
练习 3.2 通过方法修改属性(带验证)
题目:
定义类 Counter(计数器),要求:
__init__(self)中设置self.count = 0- 方法
add(self, n=1):把count加上n,但n必须大于 0,否则打印"增量必须大于 0" - 方法
reset(self):把count归零
创建实例后,依次:调用 add()(不传参,用默认 1)三次,调用 add(-1),调用 reset(),打印每步后的 count。
参考答案:
class Counter:
def __init__(self):
self.count = 0
def add(self, n=1):
if n <= 0:
print("增量必须大于 0")
return
self.count += n
def reset(self):
self.count = 0
c = Counter()
c.add()
print(c.count) # 1
c.add()
print(c.count) # 2
c.add()
print(c.count) # 3
c.add(-1) # 增量必须大于 0
print(c.count) # 3(没有变)
c.reset()
print(c.count) # 0
四、类变量 vs 实例变量
练习 4.1 用类变量记录实例数量
题目:
定义类 Dog,要求:
- 类变量
count = 0,记录共创建了多少只狗 - 每次
__init__执行时,Dog.count += 1 - 实例变量只需要
self.name
创建 3 个 Dog 实例,然后分别打印 Dog.count 和任意一个实例的 .count,观察结果是否相同。
参考答案:
class Dog:
count = 0
def __init__(self, name):
self.name = name
Dog.count += 1
d1 = Dog("旺财")
d2 = Dog("小黑")
d3 = Dog("大白")
print(Dog.count) # 3
print(d1.count) # 3(实例也能访问类变量)
练习 4.2 类变量与实例变量同名时的行为
题目:
下面代码中,对 d1.count = 999 之后,分别打印 d1.count 和 Dog.count,预测并验证输出。说明为什么两者不一样。
class Dog:
count = 0
def __init__(self, name):
self.name = name
Dog.count += 1
d1 = Dog("旺财")
d2 = Dog("小黑")
d1.count = 999
参考答案:
class Dog:
count = 0
def __init__(self, name):
self.name = name
Dog.count += 1
d1 = Dog("旺财")
d2 = Dog("小黑")
d1.count = 999
print(d1.count) # 999(d1 上创建了同名的实例变量,遮蔽了类变量)
print(Dog.count) # 2(类变量没有变)
要点: d1.count = 999 不会修改类变量,而是在 d1 上创建了一个实例变量 count,它”遮蔽”了类变量,但类变量本身完整保留。修改类变量应写 Dog.count = 新值。
五、继承
练习 5.1 子类继承父类方法
题目:
已有父类 Animal:
class Animal:
def __init__(self, name):
self.name = name
def breathe(self):
print(f"{self.name} 在呼吸")
定义子类 Dog(Animal),添加方法 bark(self),打印 "xxx:汪汪!"。
创建 Dog("旺财"),分别调用 breathe()(继承来的)和 bark()(自己的)。
参考答案:
class Animal:
def __init__(self, name):
self.name = name
def breathe(self):
print(f"{self.name} 在呼吸")
class Dog(Animal):
def bark(self):
print(f"{self.name}:汪汪!")
dog = Dog("旺财")
dog.breathe() # 旺财 在呼吸(继承自父类)
dog.bark() # 旺财:汪汪!(子类自己的)
练习 5.2 子类重写(覆盖)父类方法
题目:
在上面的基础上,再定义子类 Cat(Animal),同样覆盖 speak 方法(打印 "xxx:喵~"),父类也有 speak(打印 "xxx 发出声音")。
分别创建 Animal、Dog、Cat 三个实例,各调用 speak(),观察输出。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出声音")
参考答案:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出声音")
class Dog(Animal):
def speak(self):
print(f"{self.name}:汪汪!")
class Cat(Animal):
def speak(self):
print(f"{self.name}:喵~")
a = Animal("动物")
d = Dog("旺财")
c = Cat("咪咪")
a.speak() # 动物 发出声音
d.speak() # 旺财:汪汪!
c.speak() # 咪咪:喵~
要点: Python 调用方法时,先在”当前类”里找,找不到再去父类找。Dog 和 Cat 都有自己的 speak,所以用的是自己的,不用父类的。
六、super() 的使用
练习 6.1 子类 init 里调用 super().init()
题目:
父类 Animal(name, age) 初始化 name 和 age。
子类 Dog(Animal) 在此基础上新增属性 breed(品种)。
定义 Dog.__init__(self, name, age, breed),用 super().__init__(name, age) 先让父类完成初始化,再设 self.breed。
创建 Dog("旺财", 3, "金毛"),打印三个属性。
参考答案:
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # 先让父类初始化 name 和 age
self.breed = breed
dog = Dog("旺财", 3, "金毛")
print(dog.name) # 旺财
print(dog.age) # 3
print(dog.breed) # 金毛
练习 6.2 不调用 super().init() 会怎样?
题目:
写下面代码,运行 print(dog.name) 会发生什么?为什么?
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
# 故意不调用 super().__init__(name)
self.breed = breed
dog = Dog("旺财", "金毛")
print(dog.breed) # 可以打印
print(dog.name) # ???
参考答案:
print(dog.breed) # 金毛(breed 正常初始化了)
print(dog.name) # AttributeError: 'Dog' object has no attribute 'name'
原因: Animal.__init__ 没被调用,self.name = name 这行没有执行,所以 dog 上根本没有 name 属性,访问时报 AttributeError。
七、str 方法
练习 7.1 让 print(实例) 显示有意义的内容
题目:
给下面的 Book 类加上 __str__ 方法,让 print(book) 输出 "《书名》 作者:xxx 价格:xx 元"。
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
创建一个 Book 实例,用 print() 打印它。
参考答案:
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
def __str__(self):
return f"《{self.title}》 作者:{self.author} 价格:{self.price} 元"
book = Book("Python入门", "张三", 59)
print(book) # 《Python入门》 作者:张三 价格:59 元
八、综合练习
练习 8.1 银行账户类
题目:
定义类 BankAccount,要求:
__init__(self, owner, balance=0):初始化账户主人和余额(默认 0)deposit(self, amount):存款;若amount <= 0打印"金额必须大于 0";否则增加余额并打印"存入 xx 元,余额:xx 元"withdraw(self, amount):取款;若amount <= 0打印"金额必须大于 0";若余额不够打印"余额不足";否则扣减余额并打印"取出 xx 元,余额:xx 元"__str__:返回"账户:xxx | 余额:xx 元"
创建账户,依次存 500、取 200、取 400,打印每步结果,最后 print(账户实例) 看 __str__ 效果。
参考答案:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
print("金额必须大于 0")
return
self.balance += amount
print(f"存入 {amount} 元,余额:{self.balance} 元")
def withdraw(self, amount):
if amount <= 0:
print("金额必须大于 0")
return
if amount > self.balance:
print("余额不足")
return
self.balance -= amount
print(f"取出 {amount} 元,余额:{self.balance} 元")
def __str__(self):
return f"账户:{self.owner} | 余额:{self.balance} 元"
acc = BankAccount("小明")
acc.deposit(500) # 存入 500 元,余额:500 元
acc.withdraw(200) # 取出 200 元,余额:300 元
acc.withdraw(400) # 余额不足
print(acc) # 账户:小明 | 余额:300 元
练习 8.2 继承:储蓄账户
题目:
在上一题的 BankAccount 基础上,定义子类 SavingsAccount,要求:
__init__(self, owner, rate=0.03):调用super().__init__(owner),再设self.rate = rate- 方法
apply_interest(self):把self.balance * self.rate加到余额上,打印"计息 xx.xx 元,余额:xx.xx 元" __str__:在父类__str__基础上再追加| 利率:x%(用super().__str__()拿到父类输出再拼接)
创建储蓄账户,存 1000 元,计息两次,打印实例。
参考答案:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
print("金额必须大于 0")
return
self.balance += amount
print(f"存入 {amount} 元,余额:{self.balance} 元")
def withdraw(self, amount):
if amount <= 0:
print("金额必须大于 0")
return
if amount > self.balance:
print("余额不足")
return
self.balance -= amount
print(f"取出 {amount} 元,余额:{self.balance} 元")
def __str__(self):
return f"账户:{self.owner} | 余额:{self.balance:.2f} 元"
class SavingsAccount(BankAccount):
def __init__(self, owner, rate=0.03):
super().__init__(owner)
self.rate = rate
def apply_interest(self):
interest = self.balance * self.rate
self.balance += interest
print(f"计息 {interest:.2f} 元,余额:{self.balance:.2f} 元")
def __str__(self):
return super().__str__() + f" | 利率:{self.rate * 100:.0f}%"
sav = SavingsAccount("小红", rate=0.05)
sav.deposit(1000)
sav.apply_interest() # 计息 50.00 元,余额:1050.00 元
sav.apply_interest() # 计息 52.50 元,余额:1102.50 元
print(sav) # 账户:小红 | 余额:1102.50 元 | 利率:5%
练习 8.3 阅读题:找出代码里的错误
题目:
下面代码有 3 个错误,请找出并改正:
class Cat:
def init(self, name, age): # 错误 1
self.name = name
self.age = age
def meow(): # 错误 2
print(self.name + ":喵~")
c = Cat("咪咪", 2)
Cat.meow(c) # 错误 3
参考答案:
错误 1:def init 应该写 def __init__(两边各两个下划线),否则不会自动调用,c = Cat("咪咪", 2) 时会报错。
错误 2:def meow() 缺少 self 参数,应写 def meow(self):。
错误 3:应该用实例调用方法,即 c.meow(),而不是 Cat.meow(c)(虽然后者技术上可以用,但不是标准写法,新手容易混淆)。
改正后的代码:
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def meow(self):
print(self.name + ":喵~")
c = Cat("咪咪", 2)
c.meow() # 咪咪:喵~