16.Python中的类练习题

Python 中的类练习题

一、类的基础:定义与创建实例

练习 1.1 定义最简单的类

题目:

定义一个类 Car(汽车),要求:

  • __init__(self, brand, color) 接收品牌和颜色,分别存成 self.brandself.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

参考答案:

  • 形参nameage(定义在括号里的占位参数)
  • 实例属性self.nameself.age(用 self. 开头,绑定在实例上的属性)
  • self 代表:当前正在创建的那个实例本身,Python 会在调用时自动传入,不需要手动传

练习 1.3 每个实例的属性相互独立

题目:

用下面的 Dog 类,创建 dog1 = Dog("旺财", 3)dog2 = Dog("小黑", 2)
然后把 dog1.age 改为 5,再分别打印 dog1.agedog2.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)

分别打印两个实例的 titleprice

参考答案:

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.namep.scorep.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)

  • 如果 phoneNone,返回 "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.countDog.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 发出声音")。
分别创建 AnimalDogCat 三个实例,各调用 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 调用方法时,先在”当前类”里找,找不到再去父类找。DogCat 都有自己的 speak,所以用的是自己的,不用父类的。


六、super() 的使用

练习 6.1 子类 init 里调用 super().init()

题目:

父类 Animal(name, age) 初始化 nameage
子类 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,要求:

  1. __init__(self, owner, balance=0):初始化账户主人和余额(默认 0)
  2. deposit(self, amount):存款;若 amount <= 0 打印 "金额必须大于 0";否则增加余额并打印 "存入 xx 元,余额:xx 元"
  3. withdraw(self, amount):取款;若 amount <= 0 打印 "金额必须大于 0";若余额不够打印 "余额不足";否则扣减余额并打印 "取出 xx 元,余额:xx 元"
  4. __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,要求:

  1. __init__(self, owner, rate=0.03):调用 super().__init__(owner),再设 self.rate = rate
  2. 方法 apply_interest(self):把 self.balance * self.rate 加到余额上,打印 "计息 xx.xx 元,余额:xx.xx 元"
  3. __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

参考答案:

错误 1def init 应该写 def __init__(两边各两个下划线),否则不会自动调用,c = Cat("咪咪", 2) 时会报错。

错误 2def 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()   # 咪咪:喵~

发表评论