Python从入门到精通:(2)Python 核心进阶教程从数据结构到面向对象
上一篇我们掌握了 Python 入门基础,这一篇将聚焦核心进阶内容 —— 数据结构、函数、模块、文件操作和面向对象编程。这些是写出高效、可维护代码的关键,同样搭配了详细表格和可运行的代码示例,跟着练就能吃透!
一、核心数据结构:高效组织数据的 “容器”
数据结构是存储和处理数据的方式。Python 内置了多种实用结构,掌握它们能大幅提升代码效率。
1.1 序列类型:列表(List)与元组(Tuple)
| 类型 | 特点 | 核心操作 | 应用场景 | 
|---|---|---|---|
| 列表 | 可变(可增删改)、有序 | 增(append/insert)、删(pop/remove)、改(索引赋值)、查(索引 / 切片) | 需动态修改的数据(如待办清单) | 
| 元组 | 不可变(创建后不能改)、有序 | 查(索引 / 切片)、拆包 | 固定数据(如坐标 (x,y)、配置项) | 
💡 解释:
- 列表 适合需要频繁修改的场景;
 - 元组 更安全、内存更小,适合用作字典的键或函数返回多个值。
 
列表(List)代码示例:
# 1. 定义列表
fruits = ["apple", "banana", "cherry"]# 2. 增:添加元素
fruits.append("date")  # 末尾添加
print(fruits)  # 输出:['apple', 'banana', 'cherry', 'date']
fruits.insert(1, "orange")  # 指定位置插入
print(fruits)  # 输出:['apple', 'orange', 'banana', 'cherry', 'date']# 3. 删:移除元素
fruits.pop(2)  # 按索引删除(默认删最后一个)
print(fruits)  # 输出:['apple', 'orange', 'cherry', 'date']
fruits.remove("orange")  # 按值删除
print(fruits)  # 输出:['apple', 'cherry', 'date']# 4. 改:修改元素
fruits[0] = "grape"
print(fruits)  # 输出:['grape', 'cherry', 'date']# 5. 切片:获取子列表(左闭右开)
print(fruits[1:3])  # 输出:['cherry', 'date'](索引1到2)
print(fruits[:2])   # 输出:['grape', 'cherry'](从开头到索引1)
print(fruits[::2])  # 输出:['grape', 'date'](步长2,间隔取元素)
元组(Tuple)代码示例:
# 1. 定义元组(小括号可省略,但建议加上)
point = (3, 4)
color = "red", "green", "blue"  # 省略括号的写法# 2. 查:通过索引或切片(同列表)
print(point[0])  # 输出:3
print(color[1:])  # 输出:('green', 'blue')# 3. 不可变特性(尝试修改会报错)
try:point[0] = 5
except TypeError as e:print(e)  # 输出:'tuple' object does not support item assignment# 4. 拆包:快速提取元素
x, y = point  # 元组长度需与变量数一致
print(x, y)  # 输出:3 4# 5. 单元素元组(必须加逗号,否则会被识别为其他类型)
single = (5,)  # 正确定义
print(type(single))  # 输出:<class 'tuple'>
1.2 映射与集合:字典(Dict)与集合(Set)
| 类型 | 特点 | 核心操作 | 应用场景 | 
|---|---|---|---|
| 字典 | 键值对存储、无序(Python 3.7+ 保持插入顺序) | 增(键赋值)、删(del/pop)、查(键索引 / .get())、字典推导式 | 存储关联数据(如用户信息) | 
| 集合 | 无序、唯一元素 | 去重、交集(&)、并集(` | )、差集(-`) | 
💡 解释:
- 字典 是 Python 最常用的数据结构之一,查找效率高(O(1));
 - 集合 利用哈希表实现,天然去重,集合运算非常高效。
 
字典(Dict)代码示例:
# 1. 定义字典
user = {"name": "Alice","age": 25,"is_student": False
}# 2. 查:通过键获取值(推荐用 get,避免键不存在报错)
print(user["name"])  # 输出:Alice
print(user.get("age"))  # 输出:25
print(user.get("gender", "unknown"))  # 键不存在时返回默认值:unknown# 3. 增/改:键存在则改,不存在则增
user["age"] = 26  # 修改
user["gender"] = "female"  # 新增
print(user)  # 输出:{'name': 'Alice', 'age': 26, 'is_student': False, 'gender': 'female'}# 4. 删:删除键值对
del user["is_student"]
print(user)  # 输出:{'name': 'Alice', 'age': 26, 'gender': 'female'}# 5. 字典推导式:快速生成字典
numbers = [1, 2, 3]
square = {num: num**2 for num in numbers}
print(square)  # 输出:{1: 1, 2: 4, 3: 9}
集合(Set)代码示例:
# 1. 定义集合(去重特性)
nums = {1, 2, 2, 3, 4, 4}
print(nums)  # 输出:{1, 2, 3, 4}(自动去重)# 2. 转集合去重(列表→集合→列表)
duplicates = [5, 5, 6, 7, 7]
unique = list(set(duplicates))
print(unique)  # 输出:[5, 6, 7](顺序可能变化,因为集合无序)# 3. 集合运算
a = {1, 2, 3}
b = {3, 4, 5}
print(a & b)  # 交集:{3}(两集合都有的元素)
print(a | b)  # 并集:{1, 2, 3, 4, 5}(所有元素)
print(a - b)  # 差集:{1, 2}(a有b没有的元素)
1.3 深浅拷贝:避免 “意外修改” 的坑
| 操作 | 特点 | 适用场景 | 
|---|---|---|
| 赋值 | 共享内存地址,修改一个会影响另一个 | 无需独立副本时 | 
| 浅拷贝 | 拷贝外层容器,内层对象仍共享(如列表中的列表) | 容器内元素为不可变类型(int/str 等) | 
| 深拷贝 | 完全独立拷贝,内外层都不共享 | 容器内有可变子对象(如嵌套列表) | 
💡 解释:
- 浅拷贝 用
 copy.copy()或list[:];- 深拷贝 用
 copy.deepcopy(),适用于复杂嵌套结构。
代码示例:
import copy# 原始数据(嵌套列表,内层是可变对象)
original = [1, [2, 3]]# 1. 赋值:共享内存
assigned = original
assigned[0] = 100
assigned[1][0] = 200
print(original)  # 输出:[100, [200, 3]](原始数据被修改)# 2. 浅拷贝(copy.copy 或列表切片[:])
original = [1, [2, 3]]  # 重置原始数据
shallow_copied = copy.copy(original)  # 等价于 original[:]
shallow_copied[0] = 100  # 修改外层元素(不可变类型)
shallow_copied[1][0] = 200  # 修改内层元素(可变类型)
print(original)  # 输出:[1, [200, 3]](内层被修改,外层未改)# 3. 深拷贝(copy.deepcopy)
original = [1, [2, 3]]  # 重置原始数据
deep_copied = copy.deepcopy(original)
deep_copied[0] = 100
deep_copied[1][0] = 200
print(original)  # 输出:[1, [2, 3]](原始数据完全不受影响)
二、函数深入学习:模块化代码的核心
函数是封装代码的基本单位,掌握函数的高级用法能让代码更简洁、复用性更强。
2.1 函数基础与参数机制
| 函数要素 | 说明 | 
|---|---|
| 定义与调用 | 用 def 定义,函数名后加 () 调用 | 
| 返回值 | 用 return 返回结果,无 return 则返回 None | 
| 位置参数 | 按顺序传递的参数,必须传且个数匹配 | 
| 关键字参数 | 用 key=value 形式传递,可打乱顺序,常用于指定默认值参数 | 
| 可变参数 | *args 接收任意个位置参数(元组),**kwargs 接收任意个关键字参数(字典) | 
代码示例:
# 1. 基础函数:定义与返回值
def add(a, b):  # a和b是位置参数return a + b  # 返回计算结果result = add(3, 5)
print(result)  # 输出:8# 2. 关键字参数与默认值
def greet(name, greeting="Hello"):  # greeting有默认值,是关键字参数return f"{greeting}, {name}!"print(greet("Alice"))  # 输出:Hello, Alice!(用默认greeting)
print(greet("Bob", greeting="Hi"))  # 输出:Hi, Bob!(指定关键字参数)# 3. 可变参数:*args(接收位置参数)
def sum_numbers(*args):  # args是元组,接收任意个参数return sum(args)print(sum_numbers(1, 2, 3))  # 输出:6
print(sum_numbers(10, 20, 30, 40))  # 输出:100# 4. 可变参数:**kwargs(接收关键字参数)
def print_info(**kwargs):  # kwargs是字典for key, value in kwargs.items():print(f"{key}: {value}")print_info(name="Alice", age=25)
# 输出:
# name: Alice
# age: 25
2.2 作用域与关键字
Python 变量作用域遵循 LEGB 原则:
Local(局部) → Enclosing(嵌套) → Global(全局) → Built-in(内置)
| 关键字 | 作用 | 
|---|---|
global | 在局部作用域中声明全局变量 | 
nonlocal | 在嵌套函数中声明外层(非全局)变量 | 
代码示例:
# 全局变量
global_var = "全局变量"def outer():# 嵌套作用域变量outer_var = "外层变量"def inner():# 局部变量local_var = "局部变量"print(local_var)  # 访问局部变量# 用nonlocal访问外层变量nonlocal outer_varouter_var = "修改后的外层变量"# 用global访问全局变量global global_varglobal_var = "修改后的全局变量"inner()print(outer_var)  # 输出:修改后的外层变量(被inner修改)outer()
print(global_var)  # 输出:修改后的全局变量(被inner修改)
2.3 高级函数:闭包、装饰器、生成器
| 高级函数 | 特点 | 应用场景 | 
|---|---|---|
| 闭包 | 内层函数引用外层变量,且外层函数返回内层函数 | 封装私有变量、实现装饰器基础 | 
| 装饰器 | 不修改原函数代码,为函数添加额外功能 | 日志记录、权限校验 | 
| 生成器 | 用 yield 返回值,按需生成(节省内存) | 处理大数据流、无限序列 | 
闭包代码示例:
def make_counter():count = 0  # 外层变量,被内层函数引用def counter():nonlocal count  # 声明为非局部变量count += 1return countreturn counter  # 返回内层函数# 创建两个计数器(各自独立维护count)
counter1 = make_counter()
counter2 = make_counter()print(counter1())  # 输出:1
print(counter1())  # 输出:2
print(counter2())  # 输出:1(与counter1不干扰)
装饰器代码示例:
# 定义装饰器:记录函数执行时间
import timedef timer(func):def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)  # 执行原函数end = time.time()print(f"{func.__name__}执行时间:{end - start:.2f}秒")return result  # 返回原函数结果return wrapper# 用@语法给函数加装饰器
@timer
def slow_function(seconds):time.sleep(seconds)  # 模拟耗时操作slow_function(1)  # 输出:slow_function执行时间:1.00秒
生成器代码示例:
# 生成器函数:用yield返回值
def fibonacci(n):a, b = 0, 1for _ in range(n):yield a  # 每次调用返回一个值,暂停执行a, b = b, a + b# 生成前5个斐波那契数
for num in fibonacci(5):print(num)  # 输出:0 1 1 2 3# 生成器表达式(类似列表推导式,用())
gen = (x**2 for x in range(5))
print(list(gen))  # 输出:[0, 1, 4, 9, 16]
三、模块与包:代码组织与复用
模块(.py 文件)和包(模块目录)是 Python 组织大型项目的核心。
3.1 模块导入方式
| 导入方式 | 语法示例 | 说明 | 
|---|---|---|
| 导入整个模块 | import module | 使用时需加模块名前缀(如 module.func()) | 
| 导入模块中的指定成员 | from module import func, var | 可直接使用成员(如 func()) | 
| 导入模块并取别名 | import module as alias | 简化模块名(如 import numpy as np) | 
| 导入模块中所有成员 | from module import * | 不推荐,可能导致命名冲突 | 
💡 建议:优先使用
import module或from module import specific,避免import *。
代码示例(假设存在 mymodule.py):
# mymodule.py 内容
def add(a, b):return a + bPI = 3.14
# 导入示例
import mymodule
print(mymodule.add(2, 3))  # 输出:5
print(mymodule.PI)  # 输出:3.14from mymodule import add, PI
print(add(2, 3))  # 输出:5
print(PI)  # 输出:3.14import mymodule as mm
print(mm.add(2, 3))  # 输出:5
3.2 常用标准库
Python 自带的标准库能解决很多常见问题,无需重复造轮子:
| 库名 | 功能 | 核心用法示例 | 
|---|---|---|
time / datetime | 时间处理 | time.sleep(1)、datetime.now() | 
random | 生成随机数 | random.randint(1, 10)、random.choice([...]) | 
os | 系统操作(文件 / 目录) | os.listdir()、os.mkdir() | 
sys | 与解释器交互 | sys.argv、sys.exit() | 
代码示例:
import time
import datetime
import random
import os# 时间处理
print(datetime.datetime.now())  # 输出:当前时间(如2023-10-01 12:00:00)
time.sleep(1)  # 程序暂停1秒# 随机数
print(random.randint(1, 10))  # 输出:1-10之间的随机整数
print(random.choice(["a", "b", "c"]))  # 输出:随机选择一个元素# 系统操作
print(os.listdir("."))  # 输出:当前目录下的文件列表
os.makedirs("test_dir", exist_ok=True)  # 创建目录(已存在不报错)
3.3 包的创建与使用
包是包含多个模块的目录,需包含 __init__.py 文件(可为空):
mypackage/          # 包目录
├── __init__.py     # 包标识文件(可空,也可写初始化代码)
├── module1.py      # 模块1
└── module2.py      # 模块2
代码示例:
# mypackage/module1.py
def func1():return "来自module1的func1"
# mypackage/__init__.py(可选)
from . import module1  # 允许直接通过包访问module1
# 外部使用包
from mypackage import module1
print(module1.func1())  # 输出:来自module1的func1from mypackage.module2 import func2  # 假设module2有func2
四、文件操作与异常处理:robustness 保障
4.1 文件读写模式
| 模式 | 说明 | 适用场景 | 
|---|---|---|
r | 只读(默认),文件不存在则报错 | 读取文本文件 | 
w | 只写,文件不存在则创建,存在则覆盖 | 新建 / 覆盖文件 | 
a | 追加,文件不存在则创建,内容加在末尾 | 日志记录(不覆盖历史) | 
r+ | 读写,文件不存在则报错 | 读取并修改文件 | 
b | 二进制模式(如 rb、wb) | 处理图片、视频等二进制文件 | 
💡 最佳实践:始终使用
with open(...) as f:,自动管理文件关闭。
文本文件读写示例:
# 1. 写入文件(w模式)
with open("test.txt", "w", encoding="utf-8") as f:f.write("Hello, Python!\n")f.writelines(["第一行\n", "第二行\n"])# 2. 读取文件(r模式)
with open("test.txt", "r", encoding="utf-8") as f:print(f.read())  # 读取全部内容f.seek(0)  # 回到文件开头print(f.readline())  # 读取一行print(f.readlines())  # 读取剩余行# 3. 追加内容(a模式)
with open("test.txt", "a", encoding="utf-8") as f:f.write("追加的内容\n")
二进制文件读写示例(如图片):
# 复制图片(二进制模式)
with open("source.jpg", "rb") as src, open("copy.jpg", "wb") as dst:dst.write(src.read())
4.2 异常处理
异常处理能捕获程序错误,避免崩溃,核心语法:try-except-else-finally。
| 异常类型 | 说明 | 
|---|---|
IndentationError | 缩进错误(Python 对缩进敏感) | 
KeyError | 字典中访问不存在的键 | 
IndexError | 列表索引越界 | 
ValueError | 数据类型正确但值不合适(如 int("a")) | 
TypeError | 数据类型错误(如 1 + "a") | 
代码示例:
# 基础异常处理
try:num = int(input("请输入数字:"))result = 10 / num
except ValueError:print("输入不是有效数字!")
except ZeroDivisionError:print("不能除以0!")
else:print(f"结果是:{result}")
finally:print("操作结束")# 自定义异常
class TooBigError(Exception):passdef check_number(n):if n > 100:raise TooBigError("数字不能超过100")try:check_number(200)
except TooBigError as e:print(e)  # 输出:数字不能超过100
五、面向对象编程(OOP):抽象与封装的艺术
面向对象是大型项目的主流编程范式,核心是 “类(模板)” 和 “对象(实例)”。
5.1 类与对象基础
| 概念 | 说明 | 
|---|---|
| 类 | 用 class 定义的模板,包含属性和方法 | 
| 对象 | 类的实例(如 person = Person()) | 
| 属性 | 类 / 对象的数据(如 name、age) | 
| 方法 | 类 / 对象的函数(如 eat()、sleep()) | 
代码示例:
# 定义类
class Person:species = "人类"  # 类属性(所有实例共享)def __init__(self, name, age):self.name = name  # 实例属性self.age = agedef greet(self):return f"你好,我是{self.name},今年{self.age}岁"# 创建对象
person1 = Person("Alice", 25)
print(person1.greet())  # 输出:你好,我是Alice,今年25岁
print(Person.species)   # 输出:人类
5.2 三大特性:封装、继承、多态
| 特性 | 说明 | 
|---|---|
| 封装 | 隐藏内部实现,通过方法暴露接口 | 
| 继承 | 子类继承父类的属性和方法,可扩展 | 
| 多态 | 不同对象调用同一方法,表现出不同行为 | 
继承与多态示例:
class Animal:def __init__(self, name):self.name = namedef speak(self):raise NotImplementedError("子类必须实现speak方法")class Dog(Animal):def speak(self):return f"{self.name}汪汪叫"class Cat(Animal):def speak(self):return f"{self.name}喵喵叫"def make_speak(animal):print(animal.speak())dog = Dog("旺财")
cat = Cat("咪宝")
make_speak(dog)  # 输出:旺财汪汪叫
make_speak(cat)  # 输出:咪宝喵喵叫
5.3 高级特性:魔法方法与单例模式
| 高级特性 | 说明 | 
|---|---|
| 魔法方法 | 双下划线开头的方法(如 __init__、__str__),自动触发 | 
| 单例模式 | 确保类只有一个实例(如配置管理器) | 
魔法方法示例:
class Book:def __init__(self, title, author):self.title = titleself.author = authordef __str__(self):return f"{self.title}(作者:{self.author})"def __len__(self):return len(self.title)book = Book("Python编程", "张三")
print(book)      # 调用 __str__
print(len(book)) # 调用 __len__,输出:6
单例模式示例:
class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super().__new__(cls)return cls._instances1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # 输出:True
总结:进阶之路,实践为要
这部分内容是 Python 编程的 “中流砥柱”:
- 数据结构 决定了数据的组织效率;
 - 函数和模块 提升了代码复用性;
 - 异常处理 保障了程序稳健性;
 - 面向对象 为大型项目提供了清晰的架构。
 
