Python 面向对象高级:封装、继承、多态,一文讲透三大核心特性
前言
在之前的基础课程中,我们已经学习了如何用 class 关键字定义类、创建实例对象、使用 __init__ 构造方法等基础知识。今天我们继续深入,聊一聊面向对象编程(OOP)中的三大核心高级特性:封装、继承、多态。
如果你学过 Java,对这些概念应该不陌生。Python 在 OOP 方面与 Java 有很多相通之处,但也有自己独特的“Pythonic”玩法。本文将用大量生活化比喻带你轻松理解这些抽象概念,并掌握 Python 中的具体实现方式。
💬 热身互动:你觉得面向对象中最难理解的概念是哪个?A. 封装 B. 继承 C. 多态。先在心里投个票,学完本文再来评论区验证你的答案!
一、封装(Encapsulation)
1.1 什么是封装?
官方定义:将数据(属性)和操作数据的方法捆绑在一起,形成一个独立的单元(类),并隐藏内部实现细节,只对外暴露必要的功能。
说得通俗一点,我们来看一个生活中的例子:
🚗 汽车比喻:一辆汽车内部有引擎、变速箱、电路等成千上万个精密零件。作为驾驶员,你只需要知道怎么打火、踩油门、刹车就行,不需要理解引擎是怎么燃烧汽油推动活塞的。汽车厂商把复杂的内部零件“封装”在车里,只给你一个方向盘和几个踏板——这就是封装。
一句话总结:隐藏内部细节,暴露必要功能。
在代码中:
- 隐藏的 = 私有属性和方法(不想让外部看见的)
- 暴露的 = 公共属性和方法(对外提供服务的)
1.2 Python 中的私有成员
Java 用 private 关键字定义私有成员。Python 的做法则很“优雅”——在属性或方法名前面加两个下划线 __。
class Car:
def __init__(self, brand, owner):
self.brand = brand # 公有属性
self.__owner = owner # 私有属性
def __start_engine(self): # 私有方法
print(f"{self.brand} 引擎启动中...")
def drive(self): # 公有方法
self.__start_engine() # 内部调用私有方法
print(f"{self.__owner} 正在驾驶 {self.brand}")
⚠️ Python 没有真正的私有机制!
两个下划线只是一个约定,实际上 Python 会偷偷把 __owner 改名为 _Car__owner,这就是传说中的名称改写机制。所以你可以这样“钻空子”:
my_car = Car("比亚迪", "张三")
# 尝试直接访问私有属性会报错
# print(my_car.__owner) ❌ 报错
# 但通过名称改写可以绕过去
print(my_car._Car__owner) # 输出:张三
虽然能绕过,但不建议这样做。既然作者加了双下划线,就说明“这不归你管”,强行访问就像拆开汽车外壳直接摸引擎一样危险。
1.3 什么时候用私有成员?
当你的属性或方法不想对使用者公开时,就把它设为私有的。比如:
- 密码、密钥等敏感数据
- 各种内部辅助方法
- 不希望子类随意修改的核心逻辑
✍️ 思考一下:在你的项目中,有没有一些函数你只希望类内部调用、不想让外部直接用的?如果有,它们就是设置成私有的最佳候选。
二、继承(Inheritance)
2.1 什么是继承?
👑 皇帝与太子比喻:太子继承皇位后,就拥有了皇帝所有的公开权力。但皇帝如果藏了一笔私人财富没告诉太子,那太子就用不了这笔钱。继承也是如此——子类继承父类,可以获得父类的所有公有属性和方法,私有成员除外。
在 Java 中,我们用 extends 关键字。Python 更简洁,直接在类名后面加括号:
class Car:
def __init__(self, brand):
self.brand = brand
def run(self):
print(f"{self.brand} 正在行驶...")
# 子类继承父类
class BYD(Car):
pass
# 子类实例可以直接使用父类的方法
my_car = BYD("比亚迪汉")
my_car.run() # 输出:比亚迪汉 正在行驶...
格式:class 子类(父类):
⚠️ 重点:子类继承的是父类的公有属性和方法,私有成员不可继承。
2.2 方法重写(Override)
👑 皇帝太子继续:皇帝立规矩“大臣必须早上六点上朝”。太子登基后想立威,重新定规矩“必须凌晨四点上朝”。这种行为就是重写。
重写:子类继承父类后,如果父类的方法不满足需求,可以在子类中定义一个同名方法来覆盖父类的实现。
class Car:
def show_info(self):
print("这是一辆普通汽车")
class BYD(Car):
def show_info(self): # 重写父类方法
print("这是一辆比亚迪新能源汽车")
# 如果还想调用父类的方法,有两种方式:
# 方式1:父类名.方法名(self)
Car.show_info(self)
# 方式2:super().方法名() (推荐)
super().show_info()
调用父类被重写方法的两种方式:
| 方式 | 语法 | 说明 |
|---|---|---|
| 方式一 | 父类名.方法名(self) |
需要手动传 self |
| 方式二 | super().方法名() |
推荐,自动处理 self |
📝 注意:重写只能针对方法,属性不能重写。
2.3 多继承
👑 贪心太子比喻:太子觉得光继承皇位不够,还想继承王爷的封地。但皇帝和王爷是两个独立的人,各有各的权利。太子想同时拥有——这就是多继承。
多继承:一个子类同时继承多个父类。
Java 不支持多继承(只能“一脉单传”),但 Python 可以:
class 子类名(父类1, 父类2, 父类3):
pass
class Father:
def skill(self):
print("会武功")
class Mother:
def skill(self):
print("会唱歌")
class Child(Father, Mother): # 同时继承 Father 和 Mother
pass
xiaoming = Child()
xiaoming.skill() # 输出:会武功 (优先第一个父类)
调用顺序:当多个父类有同名方法时,默认优先使用第一个父类中的方法。可以通过以下方式查看完整调用顺序:
print(Child.__mro__) # 属性:查看方法解析顺序
print(Child.mro()) # 方法:同样功能
🔍 动手试试:试着写一个
Child(Mother, Father)调换一下顺序,看看skill()输出什么?在评论区分享你的发现。
三、多态(Polymorphism)
3.1 什么是多态?
多态:同一个方法,在不同对象上表现出不同的形态和行为。
🐱🐶 动物比喻:定义一个父类
Animal,有方法make_sound(),输出“动物在叫”。子类Cat重写为“喵喵叫”,子类Dog重写为“汪汪叫”。然后在外部定义一个函数,参数类型声明为Animal,但可以传入任意子类对象——同一个函数调用,传入不同对象就触发不同行为,这就是多态。
class Animal:
def make_sound(self):
print("动物正在叫...")
class Cat(Animal):
def make_sound(self):
print("喵喵叫~")
class Dog(Animal):
def make_sound(self):
print("汪汪叫!")
# 多态的体现:同一个函数,接收不同类型对象
def animal_sound(animal: Animal):
animal.make_sound()
# 调用时传入不同子类,表现不同
animal_sound(Cat()) # 输出:喵喵叫~
animal_sound(Dog()) # 输出:汪汪叫!
3.2 Python 的特色:鸭子类型
Python 的多态和 Java 有一个关键区别。Java 的多态必须依赖继承关系,而 Python 有一种更灵活的机制——鸭子类型。
🦆 鸭子类型:如果一只鸟走起路来像鸭子,叫起来也像鸭子,那它就是鸭子。
鸭子类型的优势:不需要继承关系,只要对象有相应的方法就能用。
class Cat:
def sound(self):
print("喵喵")
class Dog:
def sound(self):
print("汪汪")
class Duck:
def sound(self):
print("嘎嘎")
# 这个函数不要求任何特定的父类
def make_sound(obj):
obj.sound()
# 三者没有任何继承关系,但都能用
make_sound(Cat()) # 喵喵
make_sound(Dog()) # 汪汪
make_sound(Duck()) # 嘎嘎
Cat、Dog、Duck 没有继承同一个父类,但都有 sound() 方法,那就可以拿来用。这就是 Python 的“鸭子类型”——只要你长得像鸭子,你就是鸭子。
💡 Python 哲学:“If it walks like a duck and quacks like a duck, then it is a duck.”
四、总结
回顾一下,今天讲了面向对象的三大核心高级特性:
| 特性 | 核心思想 | Python 实现关键点 |
|---|---|---|
| 封装 | 隐藏内部细节,暴露必要功能 | __属性名 / __方法名 定义私有成员(约定而非强制) |
| 继承 | 子类获得父类的公有属性和方法 | class 子类(父类);支持多继承;super() 调用父类 |
| 多态 | 同一方法,不同对象,不同表现 | 方法重写 + 鸭子类型(不依赖继承) |
| 附加概念 | 说明 |
|---|---|
| 方法重写 | 子类定义与父类同名方法,覆盖父类实现 |
| 多继承 | 一个子类继承多个父类,优先使用第一个父类的同名方法 |
| 鸭子类型 | Python 特色:不依赖继承关系,只要对象有相应方法就能使用 |
🎤 结课小调查:学完本文,你觉得 Python 的哪个特性最让你惊喜?
A. 双下划线“假私有”
B. 支持多继承
C. 鸭子类型
D.super()的便捷在评论区打出你的选项,看看哪个特性最受欢迎!也欢迎分享你在项目中用过的“面向对象实战案例”。
本文为 Python 面向对象高级特性理论授课内容整理。面向对象是编程进阶的基石,熟练掌握这三大特性,你的代码设计能力将迈上一个新台阶。如果觉得有帮助,欢迎点赞、收藏、关注,我们下节课再见!
更多推荐


所有评论(0)