第一部分:初识对象
一、生活中数据的组织问题
学校开学收集学生信息时,自由填表常导致:
- 格式混乱(”我叫林军点,今年31岁” vs “姓名:周杰轮”)
- 信息缺失(籍贯未填写)
- 数据无序难以管理
标准化解决方案:
- 设计统一登记表模板(姓名/性别/国籍/籍贯/年龄)
- 打印分发标准表格
- 回收规范数据
二、程序中数据组织的困境
# 不良示范:混合数据结构
stu1 = "林俊杰,男,中国,山东,31"
stu2 = {"name": "周杰轮"}
stu3 = ["周杰轮", "男", None, None, 31]
三、面向对象解决方案
核心思想:设计模板 → 批量生产 → 规范填写
| 现实步骤 | 程序实现 | 代码示例 |
|---|---|---|
| 设计表格 | 创建类 | class Student: |
| 打印表格 | 实例化对象 | stu1 = Student() |
| 填写表格 | 属性赋值 | stu1.name = "林俊杰" |
四、类与对象实践
class Student:
name = None #
gender = None
nationality = None
native_place = None
age = None
# 创建实例
stu1 = Student() # 填写信息
stu1.name = "林俊杰"
stu1.gender = "男"
stu1.nationality = "中国"
stu1.native_place = "山东省"
stu1.age = 31
五、面向对象优势对比
| 传统方式 | 面向对象 |
|---|---|
| 数据结构混乱 | 统一规范 |
| 维护困难 | 易于扩展 |
| 无固定格式 | 类型安全 |
| 难以批量处理 | 支持批量操作 |
第二部分:类的成员方法
一、成员方法基础
class Student: # 类属性定义
name=None
def say_hi(self): # 必须包含self参数
print(f"大家好,我是{self.name}") # 通过self访问成员变量,
# 创建对象并调用方法
stu = Student()
stu.name = "陈军杰"
stu.say_hi() # 输出:大家好,我是陈军杰
二、self关键字的秘密
- 自动传递机制:Python在调用方法时自动将对象实例作为self传入
- 参数传递规则:调用时只需传递self后的参数
- 访问限制:不使用self将无法访问类的成员变量
三、方法升级-带参方法
新增say_hi2(self, msg)
参数区别:msg需要显式传递,self自动传递
演示:
class Student:
name = None #姓名
gender = None#性别
nationality = None # 国籍
native_place = None #籍贯
age = None# 年龄
def say_hi(self):
print(f"我是{self.name}")
def say_hi2(self,msg):
print(f"大家好我是{self.name},{msg}")
stu_1 =Student()
stu_1.name="林俊杰"
stu_1.say_hi2("不错呦!")
四、方法设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 高内聚 | 每个方法只完成单一功能 | calculate_gpa() 只处理成绩计算 |
| 低耦合 | 方法间尽量减少依赖 | 信息展示方法不修改数据 |
| 合理命名 | 动词开头,见名知意 | get_age() 优于 data1() |
第三部分:类与对象
一、现实事物抽象方法论
- 1. 现实世界的事物和类
属性与行为: 现实世界中的事物可以归纳为两个特征,即属性和行为。例如,做核酸的属性包括何时何地谁去做,行为包括登记检测查结果;手机的属性包括长宽高重量厂商型号,行为包括打电话上网拍照。
类描述事物: 类同样具有属性和行为,因此使用类描述现实世界中的事物是非常合适的。
- 2.为什么创建对象
设计图纸与实体: 类是程序中的设计图纸,而对象是基于图纸生产出来的具体实体。类只是一种描述,真正工作的是对象。
面向对象编程: 这种通过类创建对象并使用对象进行编程的思想,就是面向对象编程。
- 3.示例——用类与对象描述显示事物,闹钟。
import winsound
class AlarmClock:
model = None # 属性:型号
price = None # 属性:价格
def ring(self): # 行为:响铃
winsound.Beep(2000, 3000) # 2000Hz频率响3秒
# 创建实体对象
my_clock = AlarmClock()
my_clock.model=“小米智能闹钟”
my_clock.price=149
my_clock.ring()
二、面向对象三大特征初探
- 封装:将闹钟的电路原理隐藏在内部
- 继承:智能闹钟继承基础闹钟功能
- 多态:不同品牌闹钟有不同的响铃方式
三、对象生命周期图解
[类蓝图] → (实例化) → [对象实例] → (调用方法) → [行为执行]
第四部分:构造方法与魔术方法
一、构造方法
class Student:
name=None #当有构造函数赋值时,可省略
age=None #当有构造函数赋值时,可省略
tel=None #当有构造函数赋值时,可省略
def __init__(self, name, age, tel): # 构造方法
self.name = name # 属性初始化
self.age = age self.tel = tel print("学生对象已创建")
# 创建对象更高效
stu = Student("周杰轮", 31, "119") # 一行完成初始化
二、魔术方法大全
| 方法 | 触发场景 | 典型应用 |
|---|---|---|
__str__ | print(obj) | 友好对象描述 |
__lt__ | obj1 < obj2 | 年龄比较 |
__eq__ | obj1 == obj2 | 学号判等 |
__del__ | 对象销毁时 | 资源释放 |
三、构造方法最佳实践
- 必填参数放前面
- 可选参数设置默认值
- 进行基础校验
四、特殊方法实战
class EnhancedStudent(Student):
def __str__(self):
return f"学生[{self.name}],年龄{self.age}岁"
def __lt__(self, other):
return self.age < other.age
def __eq__(self, other):
return self.tel == other.tel
# 使用示例
stu1 = EnhancedStudent("林俊杰", 40, "138001")
stu2 = EnhancedStudent("周杰伦", 41, "138002")
print(stu1) # 输出:学生[林俊杰],年龄40岁
print(stu1 < stu2) # 输出:True
第五部分:封装
一、封装的双重含义
- 数据封装:将属性隐藏在类内部
- 行为封装:对外暴露安全接口
二、私有成员
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner # 公开属性
self.__balance = balance # 私有属性
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance # 通过方法访问私有属性
# 测试用例
account = BankAccount("张三", 1000)
account.__balance = 2000
account.deposit(500)
print(account.get_balance()) # 输出:1500
account.__balance = 2000 # 实际创建了新属性,不影响真实余额
三、访问控制等级
| 类型 | 命名规则 | 可见范围 |
|---|---|---|
| 公开成员 | 无下划线 | 类内外均可访问 |
| 保护成员 | _单下划线 | 约定俗成的内部使用 |
| 私有成员 | __双下划线 | 仅类内部访问 |
四、封装设计原则
- 最小暴露原则:只公开必要接口
- 防御性编程:在方法中进行参数校验
- 保持一致性:修改内部实现不影响外部调用
第六部分:继承与方法复写
继承优势:提高代码复用性,减少重复劳动,使代码结构更清晰
一、单继承示例
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name}正在进食")
class Cat(Animal):
def meow(self):
print("喵喵叫")
class cattest(Animal):
pass
# 使用继承
tom = Cat("Tom")
tom.eat() # 继承自父类
tom.meow() # 子类特有方法
pass关键字:用于占位,保证语法完整性,表示该类没有新增内容
二、多继承示例
class Camera:
def take_photo(self):
print("拍照功能")
class Phone:
def make_call(self):
print("打电话")
class SmartPhone(Camera, Phone):
def unlock(self):
print("面部解锁")
# MRO(方法解析顺序)演示
print(SmartPhone.mro()) # 显示继承顺序
注意事项:
同名成员处理:当多个父类有同名属性或方法时,按照继承顺序(从左到右)确定优先级,方法调用同样遵循从左到右的继承顺序原则.
三、复写父类成员和调用父类成员
1.复写
定义:当子类继承父类的成员属性和方法后,若对继承内容不满意,可在子类中重新定义同名属性或方法的行为。
实现方式:直接在子类中声明与父类同名的成员即可完成复写,无需特殊语法标记。
关键特点:复写后子类对象调用成员时,优先使用子类版本的内容
2.调用父类同名成员
问题场景:复写后仍需访问被覆盖的父类原始成员
核心原则:需要通过特殊语法显式调用,直接使用同名成员默认访问子类版本
调用方式:类名调用、super调用
3.示例
class Cat():
def meow(self):
print("喵喵叫")
class SmartCat(Cat):
def eat(self):
super().meow() # 先调用父类方法
print("并且正在吃猫粮")
def meow(self):
print("电子喵喵叫")
# 测试复写
smart_cat = SmartCat()
smart_cat.meow()
smart_cat.eat()
四、继承设计指南
| 情景 | 解决方案 |
|---|---|
| 需要扩展功能 | 单继承+方法复写 |
| 组合多个功能 | 多继承 |
| 避免菱形继承 | 使用Mixin类 |
| 接口标准化 | 抽象基类 |
第七部分:类型注解
一、普通类型注解深度解析
使用建议与注意事项
推荐场景:
无法直接看出变量类型时(如随机数结果、JSON解析结果)
函数返回值类型不明确时
不必要场景:
显式赋值的简单类型(如var: int = 10)
类型显而易见的情况
重要特性
非强制性:
注解类型与实际类型不符不会报错(如var: int = “str”)
仅是提示功能,不影响程序运行python
from typing import Union
#标准语法:变量: 类型 = 值
var_1: int = 10
var_2: float = 3.1415926
var_3: bool = True
var_4: str = "itheima"
class Student:
pass
stu: Student = Student()
#容器类型注解
#简易注解:
#详细注解:
#列表:
my_list: list[int] = [1,2,3]
#元组:
my_tuple: tuple[int,str,bool] = (1,"itheima",True)
#字典:
my_dict: dict[str,int] = {"itheima":666}
#注释形式语法
var_5 = random.randint(1,10) # type: int
var_6 = json.loads(data) # type: dict[str,int]
var_7 = Student() # type: Student
二、Union联合类型注解
定义: 使用Union可以定义联合类型注解,用于描述变量或函数参数/返回值可能包含的多种类型。
应用场景: 当需要描述混合类型的数据结构时使用,如列表中同时包含int和str类型元素。
导入方式:
from typing import Union
列表注解:
my_list: list[Union[int, str]] = [1, 2, "itheima", "itcast"]
字典注解:
my_dict: dict[str, Union[str, int]] = {"name":"周杰轮", "age":31}
注意事项:
Union的U必须大写
需要先导入才能使用
适用于变量、函数形参和返回值注解
第八部分:多态
一、多态定义与机制
定义:多态指多种状态,即完成某个行为时,使用不同对象会得到不同状态
实现方式:
父类定义方法但不实现(pass)
子类继承并重写父类方法
关键机制:
函数形参声明接收父类对象(类型注解)
实际传入子类对象进行工作
二、代码示例
class AC:
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 GELE_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()
midea_ac=midea_AC()
geli_ac=GELE_AC()
make_cool(midea_ac)
make_cool(geli_ac)
二、多态设计优势
| 优势 | 说明 |
|---|---|
| 接口统一 | 不同对象相同方法调用 |
| 扩展性强 | 新增子类无需修改父类 |
| 代码灵活 | 运行时动态确定对象类型 |
| 易于测试 | 可mock对象进行单元测试 |
全篇总结:面向对象编程核心要点梳理
一、面向对象三大支柱
| 特性 | 核心价值 | 典型应用场景 |
|---|---|---|
| 封装 | 数据保护与接口规范化 | 用户密码存储、硬件驱动封装 |
| 继承 | 代码复用与体系扩展 | 游戏角色系统、UI组件库 |
| 多态 | 接口统一与灵活扩展 | 支付系统对接、文件格式解析 |
二、学习路径图谱
类与对象基础 → 成员方法 → 构造方法 → 魔术方法 → 封装 → 继承体系 → 类型系统 → 设计模式
三、核心优势总结
- 工程化管理:通过类模块化组织代码
- 高复用性:继承机制减少重复代码
- 易维护性:封装保护内部实现细节
- 强扩展性:多态支持系统灵活扩展
综合案例:智能家居控制系统开发
一、系统需求分析
- 支持多种设备类型(照明/空调/安防)
- 统一控制接口
- 设备状态实时反馈
- 能耗统计功能
二、类结构设计
from typing import List, Dict
from abc import ABC, abstractmethod
class SmartDevice(ABC):
"""智能设备基类"""
def __init__(self, device_id: str, power_consumption: float):
self.__device_id = device_id # 私有属性
self._power_used = 0.0 # 保护属性
self.power_rate = power_consumption # 公开属性
@abstractmethod
def operate(self) -> None:
"""设备操作抽象方法"""
pass
@property
def device_id(self) -> str:
"""只读属性访问"""
return self.__device_id
def energy_report(self) -> Dict[str, float]:
"""能耗报告(模板方法)"""
return {
"device_id": self.__device_id,
"total_energy": self._power_used
}
class SmartLight(SmartDevice):
"""智能照明设备"""
def __init__(self, device_id: str, brightness: int = 50):
super().__init__(device_id, 0.1) # 继承构造方法
self.__brightness = brightness # 私有属性
def operate(self, level: int) -> None:
"""实现多态方法"""
if 0 <= level <= 100:
self.__brightness = level
self._power_used += self.power_rate * (level/10)
print(f"照明{self.device_id}亮度调整为{level}%")
def current_status(self) -> Dict[str, Union[str, int]]:
"""扩展方法"""
return {
"device_id": self.device_id,
"type": "照明",
"brightness": self.__brightness
}
class SmartAC(SmartDevice):
"""智能空调设备"""
def __init__(self, device_id: str):
super().__init__(device_id, 2.5)
self.__temperature = 26
def operate(self, temp: int) -> None:
"""实现多态方法"""
if 16 <= temp <= 30:
self.__temperature = temp
self._power_used += self.power_rate
print(f"空调{self.device_id}设置为{temp}℃")
class HomeController:
"""家居控制中心"""
def __init__(self):
self.__devices: List[SmartDevice] = []
def add_device(self, device: SmartDevice) -> None:
"""添加设备(类型注解)"""
self.__devices.append(device)
def batch_control(self, operation: Dict[str, int]) -> None:
"""批量控制(多态应用)"""
for device in self.__devices:
if isinstance(device, SmartLight):
device.operate(operation.get("light_level", 50))
elif isinstance(device, SmartAC):
device.operate(operation.get("ac_temp", 26))
def generate_report(self) -> List[Dict]:
"""生成报告(统一接口)"""
return [d.energy_report() for d in self.__devices]
三、系统测试演示
# 初始化系统
controller = HomeController()
# 添加设备
living_room_light = SmartLight("L-101")
bedroom_ac = SmartAC("AC-202")
controller.add_device(living_room_light)
controller.add_device(bedroom_ac)
# 批量控制
controller.batch_control({
"light_level": 75,
"ac_temp": 24
})
# 查看状态
print(living_room_light.current_status())
# 输出:{'device_id': 'L-101', 'type': '照明', 'brightness': 75}
# 生成能耗报告
print(controller.generate_report())
# 输出:[{'device_id': 'L-101', 'total_energy': 0.75},
# {'device_id': 'AC-202', 'total_energy': 2.5}]
四、案例知识点解析
| 知识点 | 应用场景 | 代码示例 |
|---|---|---|
| 抽象类 | 定义设备标准接口 | SmartDevice基类 |
| 封装 | 保护设备ID和能耗数据 | __device_id私有属性 |
| 继承 | 设备类型继承体系 | SmartLight继承SmartDevice |
| 多态 | 统一控制不同设备 | operate()方法的不同实现 |
| 类型注解 | 参数类型提示 | add_device(device: SmartDevice) |
| 魔术方法 | 状态报告生成 | energy_report()模板方法 |
| 访问控制 | 属性保护机制 | @property装饰器的使用 |