☰
Python基础语法练习题(70)
2026/10/14 5:35:22 网站建设 项目流程

紧接着是下面一题。

第七十题:子类重写父类方法

1. 原始版本:儿子借老爹的本事,再自己改口

#定义一个父类Vehicle,包含一个方法describe,用于描述车辆具体信息。
#定义一个子类Car,继承自vehicle,并重写describe方法,以提供关于汽车的特定信息

#定义父类

class Vehicle:
"""
定义一个父类Vehicle,包含一个方法describe,用于描述车辆具体信息。
"""

#初始化车辆对象

def __init__(self,make,model):

self.make = make
self.model = model

#描述车辆信息

def describe(self):

return f"这辆车的制造商是 {self.make},型号是 {self.model}。"

#定义子类,继承自父类

class Car(Vehicle):
"""
定义一个子类Car,继承自vehicle,并重写describe方法,以提供关于汽车的特定信息
"""

def __init__(self, make, model, year):

#调用父类的__init__,初始化制造商与型号
super().__init__(make, model)

#再初始化子类特有的属性
self.year = year

#重写父类方法

def describe(self):

"""
重写父类方法,提供关于汽车的特定信息
return: str
"""

return f"这辆车的年份是 {self.year}。"

#示例使用

car = Car("丰田", "卡罗拉", 2024)

#描述汽车基本信息

print(car.describe())

#调用父类的describe,展示制造商与型号信息

print(Vehicle.describe(car))

思路:这题第一次把类串成了父子关系。父类Vehicle存make和model,describe把它们描述出来。子类Car写个class Car(Vehicle),就白捡了老爹的全部家当——这就是继承。

子类比父类多了个year,但make、model没必要重写一遍。所以在子类的__init__里先super().__init__(make, model)把这两个交给老爹初始化,自己只管多出来的year。能继承就别重复造轮子。

重写就是子类重新定义同名方法,把describe换成汽车专属的。最后印两次:car.describe()走子类重写版,Vehicle.describe(car)显式点名要父类版本。同一个对象,两个describe各说各话,继承关系一下就落地了。

局限:只造一辆车、数据写死;而且子类describe只说了年份,把制造商和型号丢了,重写反而越写越窄。

2. 优化版:先选类别,再挑车,查完还能接着查

#定义一个父类Vehicle,包含一个方法describe,用于描述车辆具体信息。
#定义一个子类Car,继承自Vehicle,并重写describe方法,以提供关于汽车的特定信息。
#(优化版:两级选择——先选车辆类别,再选具体车辆查询,查完询问是否再次查询或退出)

#定义父类

class Vehicle:
"""
定义一个父类Vehicle,包含一个方法describe,用于描述车辆具体信息。
"""

#初始化车辆对象

def __init__(self, make, model):

self.make = make
self.model = model

#描述车辆信息

def describe(self):

return f"这辆车的制造商是 {self.make},型号是 {self.model}。"

#定义子类,继承自父类

class Car(Vehicle):
"""
定义一个子类Car,继承自Vehicle,并重写describe方法,以提供关于汽车的特定信息。
"""

def __init__(self, make, model, year):

#调用父类的__init__,初始化制造商与型号
super().__init__(make, model)

#再初始化子类特有的属性
self.year = year

#重写父类方法

def describe(self):

"""
重写父类方法,提供关于汽车的特定信息。
:return: str
"""

return f"这是一辆 {self.year} 年产的 {self.make} {self.model}。"

#按类别组织可查询的车辆:键是类别名,值是该类别下的车辆对象列表
#目前子类只有 Car(汽车),因此只提供“汽车”这一类别

vehicle_types = {
"汽车": [
Car("丰田", "卡罗拉", 2024),
Car("比亚迪", "汉", 2023),
Car("特斯拉", "Model 3", 2025),
],
}

#辅助函数:读取一个范围内的整数编号(带输入校验,两级菜单复用)

def read_index(prompt, count) -> int:

"""
反复提示用户输入,直到选择一个 1 ~ count 范围内的合法编号为止。
:param prompt: 输入提示信息
:param count: 可选择的数量上限
:return: 对应的列表索引(int)
"""

index = 0
valid = False

#使用标志位控制循环,循环外统一 return,避免 PyCharm 将 while True 误判为可能返回 None
while not valid:
try:
choice = int(input(prompt))
except ValueError:
print("输入无效,请输入一个数字。")
continue
#范围校验独立于 try/except,避免合法数字绕过边界判断
if 1 <= choice <= count:
index = choice - 1
valid = True
else:
print(f"输入超出范围,请输入 1 ~ {count} 之间的数字。")

return index

#辅助函数:展示某类别下的车辆列表

def show_vehicles(vehicles):

"""
打印该类别下所有车辆的编号与基本信息。
:param vehicles: 车辆对象列表
"""

for i, vehicle in enumerate(vehicles, start=1):
#子类汽车额外显示年份
print(f" {i}. {vehicle.make} {vehicle.model}({vehicle.year} 年)")

#主程序

while True:

#第一级:展示可查询的车辆类别,让用户先选择类别
type_names = list(vehicle_types.keys())

print("\n" + "=" * 40)
print("欢迎使用车辆信息查询系统,请选择要查询的车辆类别:")
print("=" * 40)

for i, name in enumerate(type_names, start=1):
count = len(vehicle_types[name])
print(f" {i}. {name}(可查询 {count} 辆)")

print("-" * 40)

type_index = read_index("请输入类别编号:", len(type_names))
selected_type = type_names[type_index]
vehicles = vehicle_types[selected_type]

#第二级:进入所选类别,展示该类别下的车辆并选择一辆查询
print(f"\n【{selected_type}】现有以下车辆可查询:")
show_vehicles(vehicles)

car_index = read_index("请输入要查询的车辆编号:", len(vehicles))
selected = vehicles[car_index]

#多态调用:子类对象执行重写后的 describe
print("查询结果:", selected.describe())

#查询完成后询问用户是再次查询还是退出程序
again = input("是否再次查询信息?(y=继续 / 其他=退出):").strip().lower()
if again != "y":
print("感谢使用,查询系统已退出。")
break

思路:继承结构没动,升级的是怎么用这些对象。子类describe改成这是一辆 {year} 年产的 {make} {model},既用继承来的make/model,又加自己的year,重写不再丢信息。

真正的变化在外层交互。单辆车太寒碜,我建了个vehicle_types字典:键是类别,值是一串Car对象。这就是“列表装对象”的升级版——字典套列表,天然适合“先分类、再在类里挑”的两级结构。

两级菜单都要“输一个 1~N 的编号”,我不写两遍,抽成read_index(prompt, count),范围上限当参数传进去,复用给类别层和车辆层。这里用了标志位循环while not valid,跳出后统一return,绕开 PyCharm 对while True可能返回None的误判。

最后走一遍:列类别 → 选类别 → 列该车队 → 选车 →selected.describe()。这句正是多态的实战:不管selected是哪辆车,统一调describe(),各自执行自己那版重写。父类子类一套接口、多种表现,这题算是把继承主题圆上了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询