Python进阶之面向对象编程

面向对象编程(Object-Oriented Programming,简称OOP) 是Python进阶的核心知识点,也是从“会写代码”到“会设计代码”的关键一步。相比面向过程的分步实现思路,面向对象以“对象”为核心组织代码,更贴合现实世界的认知逻辑,能大幅提升代码的复用性、扩展性与可维护性。

本文基于经典Python教程体系,系统拆解面向对象的全部核心内容,分为基础入门与高级特性两大部分,涵盖类与对象、self关键字、魔法方法、封装、继承、多态三大特性,以及类属性、类方法、静态方法等进阶知识点。全文配套可运行代码示例与图解说明,适合已掌握Python基础语法的读者系统学习,也可作为日常开发的知识点速查手册。


文章目录

第一部分:Python面向对象基础

1 什么是面向对象

学习目标

  1. 了解常见的编程思想分类
  2. 理解面向对象的核心概念
  3. 掌握面向对象的三大特性
1.1 两种主流编程思想

编程思想是解决问题的底层思维方式,与编程语言无关,主流分为两类:

  • 面向过程:以“步骤”为核心,将问题拆解为依次执行的函数/步骤,按流程逐步实现。适合逻辑简单的线性场景,但扩展性较弱,需求变动时修改成本高。
  • 面向对象:以“对象”为核心,将问题中的实体抽象为类,通过对象之间的交互完成需求。代码结构更灵活,扩展性、复用性更强,适合中大型项目开发。

Python同时支持两种编程范式,日常开发中通常是二者结合使用。

1.2 面向过程 vs 面向对象
1.2.1 面向过程思想

面向过程的核心是「步骤」:把解决问题的流程拆解成一个个依次执行的步骤,按照步骤编写代码逐一实现,是一种过程化的叙事思维。

生活案例:ATM取钱(面向过程视角)
在这里插入图片描述

1.2.2 面向对象思想

面向对象的核心是「对象」:不再关注执行步骤,而是将问题中的实体抽象为对象,通过对象之间的交互完成需求。
面向对象的核心理念:一切皆对象。现实世界中的冰箱、手机、汽车,乃至抽象的账户、订单,都可以被抽象为“对象”——每个对象有自己的特征(属性)和行为(方法)。

面向对象思想的优势:

  • 更贴近人类的认知习惯,代码可读性更强
  • 封装、继承、多态三大特性大幅提升代码复用性与扩展性
  • 便于模块化管理,降低大型项目的维护成本

经典案例:把大象放进冰箱
举个经典的例子:“把大象放进冰箱”。

  • 面向过程思路:打开冰箱门 → 把大象放进去 → 关上冰箱门
  • 面向对象思路:抽象出「冰箱」和「大象」两个类,冰箱有开门、关门的方法,大象有移动的方法,通过对象调用方法完成需求在这里插入图片描述
    在这里插入图片描述
1.3 面向对象的三大特性

面向对象编程有三大支柱特性,也是OOP的核心价值所在:

  1. 封装:隐藏对象的内部实现细节,仅对外暴露有限的访问接口,控制数据的读写权限,保障数据安全,简化调用逻辑。
  2. 继承:子类可以复用父类的属性和方法,无需重复编写相同代码,实现代码复用,构建类的层级体系。
  3. 多态:同一接口在不同场景下表现出不同的行为,实现框架与实现的解耦,提升代码的扩展性。

💡 通俗理解

  • 封装:我包里有什么东西、怎么放的,你不用知道,我给你什么你拿什么
  • 继承:孩子继承父母的财产和天赋,还能有自己的新能力
  • 多态:同一个“播放”按钮,点视频出画面,点音乐出声音

1.3.1 封装

封装的核心是「隐藏细节,暴露接口」:将对象的属性和实现细节隐藏起来,仅对外公开有限的访问接口,控制属性的读写权限。
封装的目的是增强代码安全性、简化调用逻辑,使用者无需了解内部实现,只需通过公开接口即可操作对象。

生活案例:小明的信息权限
不同身份的人能获取小明的信息范围不同,这就是现实中的封装:

身份 可获取的信息
银行柜员 身份证号、联系方式、银行卡号等
同事 姓名、职位、性别、年龄等
父母 血型、身份证号、情感状态等

在代码中,封装就是将数据与操作数据的方法整合为「类」,数据和函数都是类的成员。

1.3.2 继承

继承描述类与类之间的从属关系,对应现实中的「子承父业」:子类可以继承父类的属性和方法,无需重复编写相同代码。
所有继承关系都满足 is-a 原则,即「子类是父类」。

在这里插入图片描述

1.3.3 多态

多态指「同一消息,不同对象响应不同」:同一个方法调用,根据传入对象的不同,会执行不同的逻辑,呈现出多种状态。

生活案例:F12功能键
同一个F12按键,在不同软件中功能完全不同:

场景 功能
WPS办公软件 提示用户保存文件
Chrome浏览器 打开开发者工具
1.4 本节核心总结
  • 编程思想是编写代码的思维方式,分为面向过程、面向对象两类
  • 面向过程:以步骤为核心,逐行实现逻辑,扩展性较差
  • 面向对象:以对象为核心,通过类抽象现实事物,扩展性更强
  • 三大核心特性:
    • 封装:将属性与方法封装在类中,对外仅暴露访问接口
    • 继承:子类继承父类的属性与方法,实现代码复用
    • 多态:同一函数/方法在不同场景下有不同表现

2 类与对象:OOP的基础单元

学习目标

  1. 理解类与对象的概念与关系
  2. 掌握 class 关键字定义类的语法
  3. 掌握对象实例化与方法调用的写法
  4. 理解 self 关键字的作用
2.1 什么是类,什么是对象

类和对象是面向对象的两个核心概念:

  • 类(Class):对一类事物的抽象描述,是创建对象的“模板/图纸”,定义了这类事物共有的属性和方法。
  • 对象(Object):类的具体实例,是真实存在的个体,具备类定义的全部特征与行为。

简单类比:类是汽车设计图纸,对象是按照图纸生产出来的真实汽车。一张图纸可以生产无数台汽车,一个类也可以创建无数个对象。

在这里插入图片描述

2.2 类的定义

Python使用class关键字定义类,基础语法如下:

class 类名:
    # 类的属性与方法
    方法列表

命名规范:类名推荐使用大驼峰命名法,每个单词首字母大写,如CarStudentInfo

示例:定义一个汽车类

# 定义汽车类
class Car:
    # 定义“跑起来”的方法
    def run(self):
        print("汽车能跑起来了...")
2.3 对象的创建与使用

通过「类名()」即可实例化创建对象,通过「对象名.方法名()」调用类中的方法。

基础语法:

# 创建对象
对象名 = 类名()

# 调用方法
对象名.方法名()

案例:创建汽车对象并调用方法

# 1. 定义类
class Car:
    def run(self):
        print('能跑起来了...')

# 2. 创建对象
car = Car()

# 3. 调用方法
car.run()

在这里插入图片描述

2.4 self关键字

self是Python类方法中的第一个参数,也是面向对象的核心关键字之一。

  • self的本质:指向调用该方法的对象实例本身。谁调用了这个方法,self就代表谁。
  • self的作用:一个类可以创建N个对象,self用于区分不同的实例,在类内部访问对象的属性、调用其他方法。

验证:self与对象是同一个实例

class Car:
    def run(self):
        print(f'self的内存地址:{self}')
        print('能跑起来了...')

# 创建第一个对象
car = Car()
print(f'car对象的内存地址:{car}')
car.run()

print('*' * 30)

# 创建第二个对象
car2 = Car()
print(f'car2对象的内存地址:{car2}')
car2.run()

运行结果中,car对象和self的内存地址完全一致,证明二者指向同一个实例:
在这里插入图片描述
在这里插入图片描述

类内部调用其他方法
在类的方法中调用同类的其他方法,必须通过self.方法名()实现:

class Car:
    def run(self):
        print('能跑起来了...')

    def work(self):
        # 类内部调用方法,通过 self.方法名()
        self.run()

car = Car()
car.work()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⚠️ 注意
定义方法时self必须写在第一个参数位置;
调用方法时,不需要手动传递self参数,Python解释器会自动把调用对象传入。


3 对象属性的添加与访问

学习目标

  1. 掌握在类外部添加、获取对象属性的方法
  2. 掌握在类内部获取对象属性的方法
3.1 什么是属性

属性是对象的固有特征,比如人的姓名、年龄、身高、体重,汽车的颜色、轮胎数等,在代码中通过变量表示。

3.2 类外部操作属性
  • 添加/修改属性对象名.属性名 = 属性值
  • 获取属性对象名.属性名

示例:给汽车对象添加颜色、轮胎数属性

class Car:
    def run(self):
        print('能跑起来了...')

# 创建对象
car = Car()

# 类外部添加属性
car.color = "红色"
car.number = 4

# 类外部获取属性
print(f"车的颜色:{car.color}")
print(f"轮胎数量:{car.number}")
3.3 类内部获取属性

在类内部通过 self.属性名 获取对象的属性,通常封装为专门的方法对外提供访问。

示例:在类内部打印汽车信息

class Car:
    def run(self):
        print('能跑起来了...')
    
    def show(self):
        # 类内部通过 self 获取属性
        print(f"车的颜色为:{self.color}")
        print(f"轮胎个数为:{self.number}")

# 创建对象
car = Car()
# 外部设置属性
car.color = "红色"
car.number = 4
# 调用内部方法查看属性
car.show()

💡 提示
类外部动态添加属性的方式虽然灵活,但不规范。实际开发中,属性通常在构造方法__init__中统一初始化。

3.4 本节核心总结
  • 属性:对应对象的特征,本质是对象的成员变量
  • 属性操作
    • 类外部:对象名.属性名 = 值 添加/修改;对象名.属性名 获取
    • 类内部:self.属性名 访问和修改

阶段性总结

  • 编程思想
    • 面向过程:以步骤为核心,扩展性差
    • 面向对象:一切皆对象,通过类与对象模拟现实世界
  • 类与对象
    • 类:抽象模板,使用 class 类名: 定义,推荐大驼峰命名
    • 对象:具象实体,通过 对象名 = 类名() 创建,对象名.方法名() 调用方法
  • self:指向调用方法的对象本身,类内部操作属性、调用方法都依赖 self
  • 属性:对象的特征,类内外有不同的访问方式

4 核心魔法方法

学习目标

  1. 理解魔法方法的概念与特点
  2. 掌握 __init__() 构造方法的用法
  3. 掌握 __str__() 方法的作用与写法
  4. 掌握 __del__() 析构方法的作用
4.1 魔法方法的概念

魔法方法是 Python 类中特殊的方法,名称被双下划线包裹,在特定场景下会由 Python 解释器自动调用,无需开发者手动触发。它们是Python面向对象的“魔力”所在。
通用格式:__魔法方法名__()

4.2 __init__():构造方法

__init__() 也叫构造方法,在创建对象时会自动调用,用于初始化对象的属性,是最常用的魔法方法。
在这里插入图片描述

无参构造方法

无需外部传参,在类内部直接给属性设置默认值。

class Car:
    def __init__(self):
        # 初始化属性
        self.color = 'red'
        self.number = 4

    def show(self):
        print(f'车身颜色:{self.color}')
        print(f'车轮数:{self.number}')

# 创建对象,自动执行 __init__
car = Car()
car.show()

在这里插入图片描述

带参构造方法

通过外部传入参数动态初始化属性,灵活性更高,是实际开发中最常用的写法。

class Car:
    def __init__(self, color, number):
        self.color = color
        self.number = number

    def show(self):
        print(f'车身颜色:{self.color}')
        print(f'车轮数:{self.number}')

# 创建对象时传入参数
car = Car('black', 8)
car.show()

在这里插入图片描述

4.3 __str__():对象描述方法

默认情况下,print(对象) 会输出对象的内存地址。如果实现了 __str__() 方法,打印对象时会自动输出该方法返回的字符串,用于自定义对象的描述信息。

注意:__str__() 必须返回字符串类型的数据。

class Car:
    def __init__(self):
        self.color = '红色'
        self.number = 4

    def __str__(self):
        return f'{self.color}的汽车,有{self.number}个车轮'

car = Car()
print(car)
  • 未实现 __str__():输出内存地址
    在这里插入图片描述

  • 实现 __str__():输出自定义内容
    在这里插入图片描述

4.4 __del__():析构方法

__del__() 也叫析构方法,在对象被销毁时自动调用(手动 del 删除对象,或程序执行结束时),用于释放资源、清理内存。

class Car:
    def __init__(self, color):
        self.color = color

    def __del__(self):
        print('自动调用了 __del__ 魔法方法')

car = Car('红色')
del car  # 手动删除对象,触发 __del__

在这里插入图片描述

4.5 本节核心总结
  • 魔法方法特点:双下划线包裹、特定时机自动调用
  • __init__():创建对象时自动调用,用于初始化属性,支持无参、带参两种形式
  • __str__()print(对象) 时自动调用,返回自定义的对象描述字符串
  • __del__():对象销毁时自动调用,用于资源释放

5 面向对象综合案例

5.1 案例1:学生体重管理

需求描述
小明初始体重 100kg,每跑步一次体重减少 0.5kg,每大吃大喝一次体重增加 2kg。用面向对象方式实现该逻辑。

# 1. 定义学生类
class Student:
    def __init__(self):
        self.weight = 100  # 初始体重

    # 跑步方法
    def run(self):
        self.weight -= 0.5
        print(f'跑步一次,体重变为 {self.weight} kg')

    # 大吃大喝方法
    def eat(self):
        self.weight += 2
        print(f'大吃大喝一顿,体重变为 {self.weight} kg')

# 2. 创建对象
xiaoming = Student()

# 3. 调用方法
xiaoming.run()
xiaoming.eat()
xiaoming.run()
xiaoming.run()
xiaoming.run()
xiaoming.run()
xiaoming.eat()
5.2 案例2:烤地瓜

需求主线

  1. 地瓜生熟状态随烤制时间变化

    烤制时长 生熟状态
    0-3分钟 生的
    3-7分钟 半生不熟
    7-12分钟 熟了
    超过12分钟 烤糊了
  2. 支持自定义添加调料
    在这里插入图片描述

# 1. 定义地瓜类
class SweetPotato:
    def __init__(self):
        self.cook_time = 0          # 累计烤制时间
        self.cook_state = '生的'    # 当前生熟状态
        self.condi_list = []        # 添加的调料列表

    # 烤制方法
    def cook(self, time):
        self.cook_time += time
        # 根据总时长更新状态
        if 0 <= self.cook_time < 3:
            self.cook_state = '生的'
        elif 3 <= self.cook_time < 7:
            self.cook_state = '半生不熟的'
        elif 7 <= self.cook_time < 12:
            self.cook_state = '熟了'
        elif self.cook_time >= 12:
            self.cook_state = '烤糊了'

    # 添加调料
    def add_condi(self, condi):
        self.condi_list.append(condi)

    # 自定义对象输出
    def __str__(self):
        return f'这个地瓜烤了{self.cook_time}分钟,状态是{self.cook_state},添加了{self.condi_list}'

# 2. 创建对象并测试
potato = SweetPotato()
print(potato)

potato.cook(3)
potato.add_condi('蜂蜜')
print(potato)

potato.cook(5)
potato.add_condi('酱油')
print(potato)

potato.cook(6)
potato.add_condi('醋')
print(potato)

在这里插入图片描述

面向对象编程思路:

  1. 需求分析:从业务中提取实体
  2. 抽象设计:将实体封装为类,梳理属性与方法
  3. 代码实现:通过对象调用方法模拟业务逻辑

第二部分:Python面向对象高级

1 类的三种定义方式

Python中类的定义有三种写法,分为旧式类与新式类,Python3中统一推荐新式类写法。

写法 格式 说明
旧式类1 class 类名: 无括号,Python2中为旧式类
旧式类2 class 类名(): 空括号,本质和第一种一致
新式类(推荐) class 类名(object): 显式继承顶级基类object,功能最完整
# 写法1
class Teacher:
    pass

# 写法2
class Teacher():
    pass

# 写法3(推荐)
class Teacher(object):
    pass

💡 说明
Python3中所有类默认继承object,三种写法效果基本一致。但显式书写class 类名(object):更符合规范,兼容性更好,也是行业通用写法。


2 继承:代码复用的核心

学习目标

  1. 理解继承的概念与作用
  2. 掌握单继承、多继承的语法
  3. 掌握子类重写父类方法的写法
  4. 掌握调用父类方法的两种方式
  5. 了解多层继承的结构
2.1 继承的概念

继承描述类与类之间的从属关系:子类继承父类后,可以直接拥有父类的全部属性和方法,无需重复编写相同代码,大幅提升代码复用率。

  • 父类(基类):被继承的类
  • 子类(派生类):继承父类的类,可以扩展自己独有的属性和方法

生活中的继承对应“子承父业”,子女可以继承父母的财产、技能,还能发展自己的能力。

生活中的继承示例

基础语法

class 父类名(object):
    # 父类成员
    ...

class 子类名(父类名):
    # 子类自动拥有父类所有属性和方法
    ...

基础示例

# 父类
class Father(object):
    def __init__(self):
        self.gender = "男"

    def walk(self):
        print("爱好散步行走")

# 子类,继承父类
class Son(Father):
    pass

# 子类对象直接调用父类的属性和方法
son = Son()
print(son.gender)
son.walk()
2.2 单继承

单继承:一个子类只继承一个父类,是最基础的继承形式。

案例:师徒传承
摊煎饼的老师傅将配方和技术传授给徒弟。

# 师父类
class Master(object):
    def __init__(self):
        self.kofu = '[古法煎饼配方]'

    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

# 徒弟类,继承师父类
class Tudi(Master):
    pass

# 徒弟对象直接拥有师父的技术
xiaoming = Tudi()
print(xiaoming.kofu)
xiaoming.make_cake()
2.3 多继承

多继承:一个子类同时继承多个父类,拥有所有父类的属性和方法。

案例:拜师学艺+培训班学习
小明既跟着老师傅学古法技术,又在培训班学新技术。

# 师父类
class Master(object):
    def __init__(self):
        self.kofu = '[古法煎饼配方]'

    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

# 培训班类
class Heima(object):
    def __init__(self):
        self.kofu = '[AI煎饼配方]'

    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

# 徒弟类,同时继承两个父类
class Tudi(Heima, Master):
    pass

xiaoming = Tudi()
print(xiaoming.kofu)
xiaoming.make_cake()
MRO 方法解析顺序

当多个父类存在同名属性/方法时,子类默认使用第一个父类的成员。
可以通过类名.__mro__类名.mro()查看方法解析顺序(Method Resolution Order),即Python查找成员的优先级顺序。
在这里插入图片描述

print(Tudi.__mro__)
print(Tudi.mro())

在这里插入图片描述
查找顺序:子类自身 → 按继承顺序从左到右的父类 → object基类,找不到则报错。

2.4 子类重写父类同名方法和属性

当父类的方法不能满足子类需求时,子类可以定义同名的方法,覆盖父类的实现,这就是方法重写(Override)
重写后,子类对象调用该方法时,优先执行子类自己的实现。

案例:自研独创技术
小明学会两种技术后,钻研出自己的独创配方。

class Master(object):
    def __init__(self):
        self.kofu = '[古法煎饼配方]'
    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

class Heima(object):
    def __init__(self):
        self.kofu = '[AI煎饼配方]'
    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

# 子类重写同名属性和方法
class Tudi(Heima, Master):
    def __init__(self):
        self.kofu = '[独创技术]'
    
    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

xiaoming = Tudi()
print(xiaoming.kofu)
xiaoming.make_cake()
2.5 调用父类方法的两种方式

子类重写父类方法后,如果还需要使用父类的原有实现,可以手动调用父类方法,有两种实现方式:

方式1:父类名直接调用

语法:父类名.方法名(self),适合多继承场景,可以精准指定调用哪个父类。

class Tudi(Heima, Master):
    def __init__(self):
        self.kofu = '[独创技术]'
    
    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

    # 调用师父类的技术
    def master_make_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    # 调用培训班的技术
    def heima_make_cake(self):
        Heima.__init__(self)
        Heima.make_cake(self)

xiaoming = Tudi()
xiaoming.make_cake()
xiaoming.master_make_cake()
xiaoming.heima_make_cake()

在这里插入图片描述

方式2:super() 调用

语法:super().方法名(),自动按照 MRO 顺序查找父类方法,适合单继承场景,代码更简洁,维护性更好。

class Tudi(Heima):
    def __init__(self):
        self.kofu = '[独创技术]'
    
    def make_cake(self):
        print(f'使用{self.kofu}摊煎饼')

    def heima_make_cake(self):
        super().__init__()
        super().make_cake()

xiaoming = Tudi()
xiaoming.heima_make_cake()

注意:super() 适合单继承使用,多继承场景推荐使用父类名直接调用的方式。

2.6 多层继承

继承支持多层传递:C 继承 B,B 继承 A,那么 C 自动拥有 A、B 的所有属性和方法,形成继承链。

案例:技术代代相传
小明退休后,将所有技术传授给自己的徒弟。

# 徒孙类,继承徒弟类
class Tusun(Tudi):
    pass

xiaoxiaoming = Tusun()
print(xiaoxiaoming.kofu)
xiaoxiaoming.make_cake()
xiaoxiaoming.heima_make_cake()
xiaoxiaoming.master_make_cake()
2.7 本节核心总结
  • 继承:子类拥有父类的所有属性和方法,实现代码复用
  • 单继承:一个子类只有一个父类
  • 多继承:一个子类有多个父类,同名成员按 MRO 顺序优先取第一个父类
  • 方法重写:子类定义同名方法覆盖父类实现,优先调用子类方法
  • 调用父类方法:
    • 父类名.方法名(self):精准指定,适合多继承
    • super().方法名():自动查找,适合单继承
  • 多层继承:继承链逐层传递属性和方法

3 封装:隐藏细节,保障安全

学习目标

  1. 理解封装的深层含义
  2. 掌握私有属性、私有方法的定义方式
  3. 掌握私有成员的公共访问接口写法
3.1 封装的概念

封装不仅是把属性和方法写到类里,更核心的是权限控制:隐藏内部实现细节,仅对外暴露安全的访问接口,防止外部随意修改内部数据,保障数据安全与逻辑稳定。

3.2 私有属性

在属性名前加双下划线 __,即可设置为私有属性:

  • 只能在类内部直接访问
  • 类外部、子类都无法直接访问
  • 对外提供 get_xxx() 获取属性、set_xxx() 修改属性的公共方法

案例:师傅的私房钱
师傅把技术传给徒弟,但私房钱不对外暴露。

class Prentice(object):
    def __init__(self):
        self.kongfu = "[独创煎饼技术]"
        self.__money = 2000000  # 私有属性:私房钱

    # 公共方法:获取私有属性
    def get_money(self):
        return self.__money

    # 公共方法:修改私有属性
    def set_money(self, money):
        self.__money = money
3.3 私有方法

在方法名前加双下划线 __,即可设置为私有方法:

  • 只能在类内部调用
  • 对外提供公共方法来间接调用私有方法

案例:保密的制作工艺
独创配方的制作流程保密,只对外暴露成品制作的接口。

class Prentice(object):
    # 私有方法:内部核心工艺
    def __secret_make(self):
        print("独门秘方制作流程...")

    # 公共方法:对外暴露的接口
    def make_cake(self):
        self.__secret_make()

📌 封装的规范

  • 私有属性:提供get_xxx()获取、set_xxx()修改的公共方法
  • 私有方法:通过公有方法间接调用
  • 核心目的:隐藏内部实现,对外提供可控、安全的访问入口

4 多态:灵活扩展的灵魂

学习目标

  1. 理解多态的概念
  2. 掌握多态的实现条件与好处
  3. 了解抽象类的作用与用法
4.1 多态的定义

多态即「多种状态」:同一个函数/接口,传入不同的对象,会执行不同的逻辑,得到不同的结果。

class Animal(object):
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        print('汪汪汪')

class Cat(Animal):
    def speak(self):
        print('喵喵喵')

# 统一的调用接口
def make_noise(animal: Animal):
    animal.speak()

# 传入不同对象,得到不同结果
dog = Dog()
cat = Cat()
make_noise(dog)  # 汪汪汪
make_noise(cat)  # 喵喵喵
4.2 多态成立的三个条件
  1. 有继承:存在父类与子类的继承关系
  2. 方法重写:子类重写父类的同名方法
  3. 父类引用指向子类对象:函数接收父类类型参数,实际传入子类对象

实战案例:战机对战平台
搭建固定的战斗平台,一代战机、二代战机无需修改平台代码即可接入。

# 父类:一代战机
class HeroFighter(object):
    def power(self):
        return 60

# 子类:二代战机
class AdvHeroFighter(HeroFighter):
    def power(self):
        return 80

# 敌军战机
class EnemyFighter(object):
    def attack(self):
        return 70

# 战斗平台(框架代码,固定不变)
def object_play(hero: HeroFighter, enemy: EnemyFighter):
    if hero.power() > enemy.attack():
        print('英雄战机胜利,敌机失败')
    else:
        print('英雄战机失败,敌机胜利')

# 测试
hero1 = HeroFighter()
hero2 = AdvHeroFighter()
enemy = EnemyFighter()

object_play(hero1, enemy)  # 一代出战
object_play(hero2, enemy)  # 二代出战
4.3 多态的核心价值
  1. 解耦合:框架代码与具体业务实现分离,互不影响
  2. 高扩展:新增子类时,无需修改框架代码,直接继承并重写方法即可兼容
  3. 大白话理解:继承是「孩子复用父辈的东西」,多态是「父辈定下的框架,不用修改就能适配孩子的新实现」
4.4 抽象类(接口)

抽象类是特殊的父类,其中的方法只有定义没有实现(方法体为 pass),相当于制定了一套接口标准,要求所有子类必须实现这些方法。

  • 抽象类不能直接实例化
  • 作用:做顶层设计,约束子类的行为规范,配合多态实现统一调用

在这里插入图片描述

案例:空调行业标准

# 抽象类:制定空调标准
class AC(object):
    def cool_wind(self):
        """制冷"""
        pass
    def hot_wind(self):
        """制热"""
        pass
    def swing_l_r(self):
        """左右摆风"""
        pass

# 子类:美的空调,实现标准
class Midea_AC(AC):
    def cool_wind(self):
        print("美的空调核心制冷科技")
    def hot_wind(self):
        print("美的空调电热丝加热")
    def swing_l_r(self):
        print("美的空调无风感左右摆风")

# 子类:格力空调,实现标准
class GREE_AC(AC):
    def cool_wind(self):
        print("格力空调变频省电制冷")
    def hot_wind(self):
        print("格力空调电热丝加热")
    def swing_l_r(self):
        print("格力空调静音左右摆风")

# 统一调用接口
def make_cool(ac: AC):
    ac.cool_wind()

# 测试
gree_ac = GREE_AC()
midea_ac = Midea_AC()
make_cool(gree_ac)
make_cool(midea_ac)

5 面向对象的其他特性:类属性、类方法与静态方法

学习目标

  1. 区分类属性与实例属性
  2. 掌握类方法、静态方法的定义与用法
5.1 实例属性

我们之前学习的属性都是实例属性,归每个对象所有:

  • 类内部通过 self.属性名 定义
  • 类外部通过 对象名.属性名 访问
  • 每个对象的属性值相互独立,互不影响
class Phone(object):
    def __init__(self):
        self.brand = '华为'  # 实例属性

phone = Phone()
phone.color = '紫色'  # 外部添加实例属性
5.2 类属性

类属性归类本身所有,所有实例共享同一份数据,定义在类内部、方法外部。

  • 推荐通过 类名.类属性名 访问
  • 适合存储所有对象共有的数据,节省内存
class Person(object):
    count = 0  # 类属性:统计实例数量

    def __init__(self, name):
        self.name = name
        Person.count += 1

# 访问类属性
print(Person.count)
5.3 实例属性 vs 类属性
  • 实例属性:归每个对象所有,每个对象独立一份,通过self.定义。适合存储每个对象独有的数据。
  • 类属性:归类本身所有,所有实例共享同一份,定义在类内部、方法外部。适合存储所有对象共有的数据,节省内存。
class Person(object):
    count = 0  # 类属性:统计实例总数

    def __init__(self, name):
        self.name = name  # 实例属性
        Person.count += 1

# 访问类属性
print(Person.count)
5.4 三类方法对比

Python的类中有三种常见方法:实例方法、类方法、静态方法,各自用途不同。

方法类型 装饰器 首参数 核心用途 调用方式
实例方法 self 操作实例属性、调用实例方法 对象名.方法名()
类方法 @classmethod cls 操作类属性、调用类方法 类名.方法名()
静态方法 @staticmethod 无默认参数 工具类功能,不依赖类和实例 类名.方法名()
类方法

使用@classmethod装饰,第一个参数为cls,代表类本身,通常配合类属性使用。

class Dog(object):
    __total = 10  # 私有类属性

    @classmethod
    def get_total(cls):
        return cls.__total

# 调用类方法
print(Dog.get_total())
静态方法

使用@staticmethod装饰,不需要默认参数,不依赖类的任何数据,相当于写在类里的普通函数,适合工具类功能。

class Game(object):
    @staticmethod
    def show_menu():
        print("=" * 20)
        print("【1】开始游戏")
        print("【2】暂停游戏")
        print("【0】退出游戏")

# 调用静态方法
Game.show_menu()

全文总结

核心知识图谱

  1. 基础核心

    • 类是模板,对象是实例,self指向调用方法的对象本身
    • 三大魔法方法:__init__初始化、__str__描述对象、__del__销毁对象
  2. 三大特性

    • 封装:双下划线设置私有成员,对外提供公共接口,隐藏细节、保障安全
    • 继承:子类复用父类代码,支持单继承、多继承、多层继承,可重写父类方法
    • 多态:同一接口不同实现,解耦框架与业务,提升扩展性;抽象类做顶层标准
  3. 进阶特性

    • 类属性所有实例共享,类方法操作类属性,静态方法实现工具功能

写在最后

面向对象不仅是语法,更是一种设计思维。入门阶段可以多从经典案例(烤地瓜、学生管理)入手,先熟悉语法;进阶阶段可以尝试用面向对象思想重构自己的旧代码,体会封装、继承、多态带来的优势。多练多思考,才能真正吃透面向对象的精髓。

更多推荐