一、选择题(共16题)
Q1
关于继承的术语,以下描述正确的是?
A 被继承的类称为子类,继承后产生的新类称为父类
B 父类是被继承的类,子类继承父类后形成的新类称为派生类
C 派生和继承是相反的动作,派生是从子类产生父类
D 扩展是指子类删除父类中不需要的方法
✓ 正确
解析:父类/基类是被继承的类;子类/派生类/扩展类是继承后形成的新类。"派生"和"继承"是同一动作的不同视角(从父类角度看是派生,从子类角度看是继承)。扩展是子类新增自己独有的能力,不是删除。
Q2
子类重写父类方法后,调用该方法时的查找顺序是?
A 先找父类 → 再找子类 → 找到即停止
B 同时查找父类和子类,合并结果
C 先找子类 → 再找父类 → 找到即停止(就近原则)
D 随机选择一个版本执行
✓ 正确
解析:方法查找遵循"就近原则":先在子类中查找,找到就直接执行;找不到才去父类找。这就是为什么重写能生效——子类版本"更近"。
Q3
多继承和多层继承的本质区别是什么?
A 多继承是"平行多个父类",多层继承是"纵向层级链路"
B 多继承就是多层继承,只是叫法不同
C 多继承只能有2个父类,多层继承可以有任意层级
D 多继承的子类不需要调用父类方法
✓ 正确
解析:多继承是一个子类同时继承多个父类(横向扩展),多层继承是 A→B→C 的纵向继承链。两者完全不同,当多继承出现同名冲突时需要用 MRO 判定调用顺序。
Q4
super() 和"父类名.方法(self)"完全等价,没有任何区别。
✓ 正确
解析:两者有区别。① super() 不需要手动传 self,父类名调用必须传;② 在多继承场景下 super() 按 MRO 顺序调用,父类名调用则直接指定;③ super() 更易维护,父类名变更时不需要修改代码。教学上建议先理解父类名调用,再掌握 super()。
Q5
在 Python 中,如何查看多继承下的方法解析顺序(MRO)?
A Child.parents()
B Child.inherits()
C Child.mro() 或 Child.__mro__
D dir(Child)
✓ 正确
解析:MRO(Method Resolution Order)可以通过
类名.mro() 或
类名.__mro__ 查看。课堂结论:多继承行为不要靠感觉,先看 MRO 再判断。
Q6
强类型语言中"真正的多态"需要满足哪三个条件?
A ① 有继承 ② 有重写 ③ 父类引用指向子类对象
B ① 有接口 ② 有实现 ③ 有注解
C ① 有类 ② 有对象 ③ 有方法
D ① 有多继承 ② 有 super() ③ 有 MRO
✓ 正确
解析:真多态三条件:继承关系 + 子类重写 + 父类引用指向子类对象。多态的价值在于"统一调用接口,降低分支判断,提高扩展性"。
Q7
Python 中,即使两个类没有继承关系,只要它们有同名方法,就可以实现"伪多态"(鸭子类型)。
✓ 正确
解析:Python 是动态类型语言,不强制要求继承关系。只要对象有同名方法就可以调用,这就是"鸭子类型"——如果它走路像鸭子,叫起来像鸭子,它就是鸭子。如果需要严格限制,可以用
isinstance() 做类型检查。
Q9
为什么 self.count += 1 可能造成类属性统计异常?
A Python 不允许在实例方法中修改类属性
B 可能在实例上创建同名属性,遮蔽了类属性
C 类属性是只读的,不能修改
D self 无法访问类属性
✓ 正确
解析:self.count += 1 相当于
self.count = self.count + 1,赋值操作会在实例上创建同名属性,从而"遮蔽"类属性。推荐用
类名.count += 1 来修改类属性。
Q10
判别成员方法、类方法、静态方法的口诀是什么?
A 看方法名长度
B 看是否有 return 语句
C 看方法定义的位置
D 用 self 是成员方法,用 cls 是类方法,都不用是静态方法
✓ 正确
解析:判别口诀:第一个参数是
self → 成员方法;有
@classmethod 且第一个参数是
cls → 类方法;有
@staticmethod 且没有 self/cls → 静态方法。
Q11
以下代码中,get_count() 属于什么类型的方法?
class Tool:
count = 0
@classmethod
def get_count(cls):
return cls.count
A 成员方法
B 类方法
C 静态方法
D 私有方法
✓ 正确
解析:有
@classmethod 装饰器且第一个参数是
cls,所以是类方法。类方法用于操作类级状态(如这里的
count 类属性)。
Q12
在 Python 中如何定义私有属性?
A 属性名前加一个下划线 _name
B 使用 private 关键字
C 属性名前加双下划线 __name
D 在类外部定义属性
✓ 正确
解析:Python 的私有权限通过在属性名/方法名前加双下划线
__ 实现。单下划线
_ 只是约定(表示"受保护"),不会真正阻止外部访问。类外部通常通过
get_xx/
set_xx 公共接口间接访问私有属性。
Q13
含有抽象方法的抽象类可以直接实例化。
✓ 正确
解析:含有抽象方法的类不能直接实例化,因为抽象方法尚未被完整实现。子类必须实现所有抽象方法后才能创建实例。抽象类的作用是"规定子类必须实现的方法规范"。
Q17
以下代码的输出是什么?
class A:
count = 0
def add(self):
A.count += 1
a1 = A()
a2 = A()
a1.add()
a2.add()
print(A.count)
✓ 正确
解析:输出
2。因为这里使用了
A.count += 1(通过类名修改),两次调用都会正确修改共享的类属性。如果写成
self.count += 1,则会创建实例属性,类属性保持为 0。
Q18
在 Python 中,可以使用 isinstance(a, Animal) 来做类型检查,限制多态调用的参数类型。
✓ 正确
解析:正确。虽然 Python 默认支持鸭子类型(伪多态),但可以通过
isinstance() 收紧类型约束,实现接近强类型语言的真多态效果。
Q19
关于 super().__init__() 和 Parent.__init__(self),描述错误的是?
A super() 不需要手动传 self
B 父类名调用需要手动传 self
C 在多继承中 super() 按 MRO 顺序调用
D super() 只能调用父类的 __init__ 方法
✓ 正确
解析:D 是错误描述。super() 可以调用父类的任何方法,不仅仅是
__init__。例如
super().move() 调用父类的 move 方法。
Q20
以下代码的运行结果是?
class Parent:
def show(self):
print("Parent")
class Child(Parent):
def show(self):
print("Child")
c = Child()
c.show()
A 先输出 Parent,再输出 Child
B 只输出 Child
C 只输出 Parent
D 报错
✓ 正确
解析:只输出
Child。子类重写了 show 方法,根据"就近原则",调用时优先执行子类版本。如果想同时保留父类逻辑,需要在子类 show 中调用
super().show()。
二、填空题(共4题)
Q8
在类中方法外定义的属性属于 ,所有对象共享同一份数据。
✓ 正确
解析:类属性定义在类体中、方法外,属于类本身,所有实例对象共享。与成员属性(实例属性通过
self.xxx 定义)不同,成员属性每个对象各有一份。
Q14
请在空白处填入合适的代码,使子类正确调用父类的 __init__:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
.__init__(name)
self.breed = breed
✓ 正确
解析:答案为
super()。Python3 推荐的写法,不需要手动传 self。也可以写
Animal.__init__(self, name),但 super() 更简洁、更易维护。
Q15
补全代码,使 age 成为私有属性:
class Girl:
def __init__(self):
self.name = "小美"
self. = 18
✓ 正确
解析:答案为
__age(注意是 age 不是 _age)。在属性名前加双下划线即定义为私有属性,类外部无法直接访问。
Q16
补全抽象方法的声明,使子类必须实现 call 方法:
from abc import ABC, abstractmethod
class AnimalBase(ABC):
def call(self):
pass
✓ 正确
解析:答案为
@abstractmethod。用该装饰器标记的方法为抽象方法,子类必须重写实现,否则子类也无法实例化。