目录
pip 安装包时出现权限错误(macOS/Linux 系统)
MySQL(使用mysql-connector-python)
密码存储:使用哈希算法(如 bcrypt),不存储明文密码。
MySQL(使用mysql-connector-python)
使用concurrent.futures.ThreadPoolExecutor
使用concurrent.futures.ProcessPoolExecutor
方式一:使用类实现(__enter__和__exit__方法)
方式二:使用@contextlib.contextmanager装饰器
优先使用contextlib.contextmanager:
一、引言
为什么选择 Python?
Python 是一门简洁、易读、功能强大的编程语言,被誉为 “最适合零基础入门的语言”,其核心优势包括:
- 简单易学:语法接近自然语言,代码量少(同等功能下仅为 Java/C++ 的 1/3 - 1/2),适合快速上手。
- 应用广泛:覆盖Web 开发(Django/Flask)、数据分析(Pandas/Numpy)、人工智能(TensorFlow/PyTorch)、自动化脚本、科学计算、爬虫等领域。
- 生态丰富:拥有超过 35 万个第三方库(如
requests
爬取网页、matplotlib
绘图),几乎能实现任何需求。 - 跨平台兼容:代码可在 Windows/macOS/Linux 等系统无缝运行,适合开发跨平台应用。
一句话总结:无论你是想零基础入门编程,还是想用代码解决工作 / 学习中的实际问题(如处理 Excel、自动化办公),Python 都是最佳选择。
Python 的历史与特性
起源与发展
- 由荷兰程序员Guido van Rossum于 1989 年开发,命名灵感来自英国喜剧《蒙提・派森的飞行马戏团》(Monty Python's Flying Circus)。
- 设计哲学:“优雅”“明确”“简单”(例如用
if
/else
等英文单词作为关键字,而非符号)。 - 版本现状:
- Python 3.x:当前主流版本(如 3.12),全面支持 Unicode,性能更强,推荐新手直接学习。
- Python 2.x:已停止维护(最后版本 2.7.18),逐步被淘汰。
核心特性
- 动态类型语言:变量无需预先声明类型(如
x = 10
是整数,x = "Hello"
可直接变为字符串)。 - 解释型语言:代码直接由解释器逐行执行,无需编译,适合快速调试(但运行速度略慢于编译型语言如 C++)。
- 面向对象编程(OOP):支持类、对象、继承、多态等特性,适合构建大型程序。
- 函数式编程:提供
lambda
表达式、map()
、filter()
等工具,写法简洁灵活。
零基础入门:你需要准备什么?
开发环境搭建
-
安装 Python:
- 官网下载:python.org(选择 Python 3.x 最新版本,勾选 “Add Python to PATH”)。
- 验证安装:打开命令提示符(CMD)或终端,输入
python --version
,显示版本号即成功(如Python 3.12.0
)。
-
集成开发环境(IDE):
- 新手推荐:VS Code(轻量、插件丰富,安装 Python 插件后支持代码补全、调试)。
- 进阶选择:PyCharm(专业级 IDE,适合大型项目,内置调试器、版本控制等功能)。
第一个 Python 程序:Hello World
print("Hello, World!") # 输出文本到控制台
- 运行方式:在 IDE 中直接点击运行按钮,或在命令行输入
python 文件名.py
。 - 代码解析:
print()
是 Python 的内置函数,用于输出内容,括号内的字符串需用英文引号包裹。
学习路径:从入门到实践
基础语法
-
核心内容:
- 变量与数据类型(整数、浮点数、字符串、列表、字典等)。
- 流程控制(
if
条件判断、for
/while
循环)。 - 函数定义与调用(封装重复代码)。
-
学习建议:
- 通过练习巩固,例如:
- 计算圆的面积:输入半径,用公式
面积 = π * r²
输出结果。 - 循环打印 1-100 内的偶数。
进阶知识
-
核心内容:
- 面向对象编程(类与对象、继承、多态)。
- 文件操作(读写文本 / JSON/CSV 文件,如读取学生成绩表并计算平均分)。
- 异常处理(处理程序运行中的错误,如文件不存在时提示用户)。
-
学习建议:
- 结合小项目实践,例如:
- 开发一个 “图书管理系统”,用类表示书籍和用户,实现借书、还书功能。
- 编写脚本自动读取 Excel 数据并生成统计报表。
实战应用(按需选择方向)
-
方向 1:自动化办公
- 库:
openpyxl
(操作 Excel)、python-pptx
(生成 PPT)、pyautogui
(模拟鼠标键盘操作)。 - 案例:批量重命名文件、自动发送邮件、提取 PDF 文本。
- 库:
-
方向 2:数据分析与可视化
- 库:
Pandas
(数据清洗)、Matplotlib
/Seaborn
(绘图)、NumPy
(数值计算)。 - 案例:分析电商销售数据,生成销量趋势图。
- 库:
-
方向 3:Web 开发
- 框架:
Django
(适合大型项目,自带管理后台)、Flask
(轻量级,适合快速开发)。 - 案例:搭建个人博客、Todo 待办事项系统。
- 框架:
-
方向 4:人工智能与机器学习
- 库:
Scikit-learn
(机器学习算法)、TensorFlow
/PyTorch
(深度学习)。 - 案例:训练图像分类模型、预测房价走势。
- 库:
学习资源推荐
免费教程与书籍
-
入门首选:
- 官方文档:Python 3 教程(权威但需一定基础)。
- 《Python 编程从入门到实践》:适合零基础,含实战项目(如开发游戏、数据可视化)。
-
进阶提升:
- 《流畅的 Python》:深入讲解 Python 核心特性(如生成器、装饰器)。
- 《利用 Python 进行数据分析》:聚焦 Pandas 库的实战应用。
在线编程平台
- LeetCode/ 力扣:刷题提升算法能力(适合准备面试)。
- Codewars:通过有趣的代码挑战练习语法(如解决数学问题、字符串处理)。
- 菜鸟教程:提供交互式代码编辑器,可直接在线运行 Python 代码。
社区与工具
- Stack Overflow:全球最大编程问答社区,遇到问题直接搜索(如 “Python list 去重”)。
- 知乎 / 微信公众号:关注 “Python 程序员”“机器之心” 等账号,获取行业动态与技巧。
- PyPI 官网:查询第三方库文档(如
requests
的用法):pypi.org。
给新手的建议:别怕犯错!
- 动手实践:编程是 “做中学” 的技能,每天至少写 30 分钟代码,哪怕只是复现示例。
- 主动提问:遇到报错(如
SyntaxError
)不要慌,学会解读错误信息(通常会告诉你哪一行代码有问题)。 - 从小项目开始:避免一上来就挑战复杂项目,先实现简单功能(如 “猜数字游戏”“计算器”)。
- 保持耐心:Python 语法简单,但进阶知识(如异步编程、内存管理)需要时间积累,允许自己逐步成长。
结语:Python 是通向编程世界的钥匙
无论你是想掌握一项新技能、提高工作效率,还是探索人工智能等前沿领域,Python 都能为你打开一扇门。现在就打开编辑器,写下第一行 print("Hello, Python!")
,开启属于你的编程之旅吧!🚀
二、Python 基础
1.Python 安装与环境配置
Python 安装步骤
-
下载 Python 安装包
- 访问 Python 官方网站:Download Python | Python.org
- 依据自身系统(Windows、macOS、Linux)挑选合适的安装包。
- 安装时要勾选 “Add Python to PATH”(此选项仅 Windows 系统有)。
-
执行安装程序
- 对于 Windows 系统,运行下载好的.exe 文件,按照安装向导的提示完成安装。
- macOS 系统可使用 Homebrew 进行安装,命令为:
brew install python3
。 - Linux 系统一般已预装 Python,若需更新版本,可使用包管理器,例如:
sudo apt-get install python3
。
-
验证安装结果
- 打开命令提示符或终端。
- 输入
python --version
或者python3 --version
,若显示 Python 版本号,则表明安装成功。
环境配置方法
-
使用虚拟环境(推荐做法)
-
创建虚拟环境:
python -m venv myenv # Windows系统 python3 -m venv myenv # macOS/Linux系统
-
激活虚拟环境:
myenv\Scripts\activate # Windows系统 source myenv/bin/activate # macOS/Linux系统
-
退出虚拟环境:
deactivate
-
-
包管理工具(pip)
-
升级 pip:
python -m pip install --upgrade pip
-
安装包:
pip install package_name
-
查看已安装的包:
pip list
-
导出依赖项:
pip freeze > requirements.txt
-
安装依赖项:
pip install -r requirements.txt
-
开发工具推荐
-
集成开发环境(IDE)
- PyCharm:功能完备,对大型项目支持良好。
- VS Code:轻量级且可通过插件扩展功能,还能搭配 Python 扩展使用。
-
文本编辑器
- Sublime Text
- Atom
常见问题及解决办法
-
PATH 环境变量未正确设置(Windows 系统)
- 手动将 Python 安装目录(例如
C:\Python39
)和脚本目录(例如C:\Python39\Scripts
)添加到系统 PATH 环境变量中。
- 手动将 Python 安装目录(例如
-
pip 安装包时出现权限错误(macOS/Linux 系统)
- 不要使用
sudo pip install
,应在虚拟环境中安装包,或者使用--user
参数:bash
pip install --user package_name
- 不要使用
-
Python 2 和 Python 3 共存
- 在命令中明确使用
python3
和pip3
来调用 Python 3 版本。
- 在命令中明确使用
2.Python 语法基础
基本语法规则
-
代码注释
# 这是单行注释 """ 这是多行注释 可以写很多内容 """
-
变量与数据类型
# 变量无需声明,直接赋值 x = 10 # 整数 y = 3.14 # 浮点数 name = "Alice" # 字符串 is_student = True # 布尔值
-
数据结构
# 列表(动态数组) fruits = ["apple", "banana", "cherry"] fruits.append("orange") print(fruits[0]) # 输出: apple # 元组(不可变数组) point = (10, 20) # 字典(键值对) person = { "name": "Bob", "age": 30, "city": "New York" } print(person["age"]) # 输出: 30
控制流语句
-
条件语句
x = 15 if x > 10: print("x大于10") elif x == 10: print("x等于10") else: print("x小于10")
-
循环语句
# for循环 for i in range(5): # 输出0到4 print(i) # while循环 count = 0 while count < 5: print(count) count += 1 # 遍历列表 fruits = ["apple", "banana", "cherry"] for fruit in fruits: print(fruit)
函数与模块
-
定义函数
def add(a, b): """返回两个数的和""" return a + b result = add(3, 5) print(result) # 输出: 8
-
导入模块
# 导入整个模块 import math print(math.sqrt(16)) # 输出: 4.0 # 导入特定函数 from random import randint print(randint(1, 10)) # 输出1到10之间的随机整数
类与面向对象
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name}")
# 创建对象
p1 = Person("Alice", 25)
p1.greet() # 输出: Hello, my name is Alice
文件操作
# 写入文件
with open("test.txt", "w") as f:
f.write("Hello, World!\n")
# 读取文件
with open("test.txt", "r") as f:
content = f.read()
print(content) # 输出: Hello, World!
异常处理
try:
x = 1 / 0 # 会引发除零错误
except ZeroDivisionError:
print("Error: 除数不能为零")
finally:
print("无论是否发生异常,都会执行这里")
常用内置函数
print()
:打印输出len()
:返回对象长度type()
:返回对象类型input()
:获取用户输入range()
:生成整数序列str()
,int()
,float()
:类型转换
编码规范
- 使用 4 个空格缩进(不要用 Tab)
- 变量名采用小写字母,单词间用下划线分隔(snake_case)
- 类名使用大写字母开头的驼峰命名法(CamelCase)
- 每行代码长度尽量不超过 79 个字符
- 使用空行分隔代码块,提高可读性
3.函数与模块
函数详解
函数定义与调用
def calculate_area(radius):
"""计算圆的面积"""
return 3.14 * radius ** 2
# 调用函数
area = calculate_area(5)
print(area) # 输出: 78.5
参数类型
- 必需参数:调用时必须传入
def add(a, b): return a + b
- 关键字参数:调用时指定参数名
add(b=3, a=2) # 等价于 add(2, 3)
- 默认参数:定义时指定默认值
def greet(name="Guest"): print(f"Hello, {name}")
- 可变参数:接受任意数量的参数
def sum_all(*args): return sum(args)
返回值
函数可以返回多个值(元组形式)
def get_name_and_age():
return "Alice", 25
name, age = get_name_and_age()
匿名函数(lambda)
square = lambda x: x ** 2
print(square(4)) # 输出: 16
模块详解
模块定义与导入
- 定义模块:创建一个
.py
文件,例如math_utils.py
# math_utils.py def add(a, b): return a + b def multiply(a, b): return a * b
- 导入模块:
import math_utils print(math_utils.add(3, 4)) # 输出: 7
- 导入特定函数:
from math_utils import multiply print(multiply(3, 4)) # 输出: 12
- 导入所有内容:
from math_utils import *
模块别名
import math_utils as mu
print(mu.add(3, 4))
内置模块
Python 提供了丰富的内置模块,例如:
import random
print(random.randint(1, 10)) # 随机整数
import os
print(os.getcwd()) # 获取当前工作目录
import datetime
print(datetime.datetime.now()) # 当前时间
包(Package)
- 包是包含多个模块的目录,目录中必须包含
__init__.py
文件(Python 3.3 + 之后可以省略) - 例如:
mypackage/ __init__.py module1.py module2.py
- 导入包中的模块:
from mypackage import module1
函数与模块最佳实践
函数设计原则
- 单一职责:每个函数只做一件事
- 文档字符串:使用
"""文档内容"""
为函数添加说明def calculate_area(radius): """ 计算圆的面积 参数: radius (float): 圆的半径 返回: float: 圆的面积 """ return 3.14 * radius ** 2
模块组织原则
- 将相关函数放在同一个模块中
- 使用
if __name__ == "__main__"
确保模块作为脚本运行时执行特定代码# math_utils.py def add(a, b): return a + b if __name__ == "__main__": # 测试代码,模块被导入时不会执行 print(add(1, 2))
避免命名冲突
- 使用模块别名或相对导入
- 避免使用
from module import *
常见问题与解决
循环导入问题
- 问题:两个模块互相导入对方
- 解决:重构代码,将共享功能移到第三个模块
模块搜索路径
- Python 按以下顺序搜索模块:
- 当前目录
- 环境变量
PYTHONPATH
指定的路径 - Python 安装的默认库路径
- 查看模块搜索路径:
import sys print(sys.path)
4.数据结构
列表(List)
特点:动态数组,有序,可变,允许重复元素。
核心操作
# 创建与访问
fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # 访问首个元素
print(fruits[-1]) # 访问最后一个元素
# 修改元素
fruits[1] = "grape" # ['apple', 'grape', 'cherry']
# 添加元素
fruits.append("orange") # 末尾添加
fruits.insert(1, "lemon") # 指定位置插入
# 删除元素
del fruits[2] # 删除指定索引元素
fruits.remove("apple") # 删除首个匹配值
popped = fruits.pop() # 删除并返回末尾元素
常用方法
len(fruits) # 列表长度
fruits.index("grape") # 查找元素索引
fruits.count("grape") # 统计元素出现次数
fruits.sort() # 升序排序
fruits.reverse() # 反转列表
列表推导式
# 生成平方数列表
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
# 条件过滤
evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]
元组(Tuple)
特点:不可变数组,有序,允许重复元素。
核心操作
# 创建元组
point = (10, 20)
person = ("Alice", 25, "New York")
# 访问元素(与列表相同)
print(person[0]) # 输出: Alice
# 元组不可修改!以下代码会报错:
# person[1] = 26 # TypeError
应用场景
- 函数返回多值:
def get_name_and_age(): return "Bob", 30 # 返回元组 name, age = get_name_and_age() # 元组解包
- 不可变数据:如字典的键、集合的元素。
集合(Set)
特点:无序,唯一元素,支持数学集合运算。
核心操作
# 创建集合
fruits = {"apple", "banana", "cherry"}
# 添加元素
fruits.add("orange") # {'apple', 'banana', 'cherry', 'orange'}
# 删除元素
fruits.remove("banana") # {'apple', 'cherry', 'orange'}
# 判断元素是否存在
print("apple" in fruits) # 输出: True
集合运算
a = {1, 2, 3}
b = {3, 4, 5}
# 并集
print(a | b) # {1, 2, 3, 4, 5}
# 交集
print(a & b) # {3}
# 差集
print(a - b) # {1, 2}
# 对称差集
print(a ^ b) # {1, 2, 4, 5}
字典(Dictionary)
特点:键值对存储,无序(3.7 + 版本后有序),键必须唯一且不可变。
核心操作
# 创建字典
person = {
"name": "Alice",
"age": 25,
"city": "New York"
}
# 访问值
print(person["name"]) # 输出: Alice
# 修改值
person["age"] = 26 # {'name': 'Alice', 'age': 26, 'city': 'New York'}
# 添加键值对
person["job"] = "Engineer" # 新增键值对
# 删除键值对
del person["city"] # {'name': 'Alice', 'age': 26, 'job': 'Engineer'}
常用方法
# 获取所有键
print(person.keys()) # dict_keys(['name', 'age', 'job'])
# 获取所有值
print(person.values()) # dict_values(['Alice', 26, 'Engineer'])
# 获取所有键值对
print(person.items()) # dict_items([('name', 'Alice'), ('age', 26), ('job', 'Engineer')])
# 安全获取值
print(person.get("age")) # 输出: 26
print(person.get("salary", 0)) # 输出: 0(默认值)
字典推导式
# 生成平方数映射
squares = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
数据结构选择指南
数据结构 | 特点 | 适用场景 |
---|---|---|
列表(List) | 有序,可变,允许重复 | 需要频繁增删改查的序列 |
元组(Tuple) | 有序,不可变 | 固定数据、函数返回多值 |
集合(Set) | 无序,唯一,支持运算 | 去重、数学集合运算 |
字典(Dictionary) | 键值对,高效查找 | 需要通过键快速查找值的场景 |
高级应用
嵌套数据结构
# 列表嵌套字典
students = [
{"name": "Alice", "age": 20},
{"name": "Bob", "age": 22}
]
# 访问嵌套数据
print(students[0]["name"]) # 输出: Alice
常用操作性能对比
操作 | 列表(List) | 字典(Dictionary) |
---|---|---|
随机访问 | O(1) | O(1) |
插入 / 删除末尾 | O(1) | O(1) |
插入 / 删除中间 | O(n) | O(1) |
查找元素 | O(n) | O(1) |
三、面向对象编程
1.类与对象
类的定义与实例化
class Person:
# 类属性(所有实例共享)
species = "Homo sapiens"
# 构造方法,初始化实例属性
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 实例方法
def greet(self):
return f"Hello, my name is {self.name} and I'm {self.age} years old."
# 创建对象(实例化)
p1 = Person("Alice", 25)
p2 = Person("Bob", 30)
# 访问属性和方法
print(p1.name) # 输出: Alice
print(p1.greet()) # 输出: Hello, my name is Alice and I'm 25 years old.
print(Person.species) # 输出: Homo sapiens
继承与多态
单继承
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement this method")
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
# 多态示例
def animal_speak(animal):
print(animal.speak())
dog = Dog("Buddy")
cat = Cat("Whiskers")
animal_speak(dog) # 输出: Buddy says Woof!
animal_speak(cat) # 输出: Whiskers says Meow!
多继承
class Flyable:
def fly(self):
return "I can fly!"
class Swimmable:
def swim(self):
return "I can swim!"
class Duck(Flyable, Swimmable):
pass
duck = Duck()
print(duck.fly()) # 输出: I can fly!
print(duck.swim()) # 输出: I can swim!
封装与访问控制
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有属性(双下划线)
def deposit(self, amount):
self.__balance += amount
def withdraw(self, amount):
if amount <= self.__balance:
self.__balance -= amount
return True
return False
def get_balance(self):
return self.__balance
# 使用封装
account = BankAccount(1000)
account.deposit(500)
print(account.get_balance()) # 输出: 1500
# 无法直接访问私有属性
# print(account.__balance) # 报错: AttributeError
特殊方法(魔术方法)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 字符串表示
def __str__(self):
return f"Point({self.x}, {self.y})"
# 加法运算符重载
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
# 长度
def __len__(self):
return 2
# 使用特殊方法
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = p1 + p2
print(p3) # 输出: Point(4, 6)
print(len(p3)) # 输出: 2
类方法与静态方法
class Person:
count = 0 # 类属性
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
@staticmethod
def is_adult(age):
return age >= 18
# 使用类方法
p1 = Person("Alice")
p2 = Person("Bob")
print(Person.get_count()) # 输出: 2
# 使用静态方法
print(Person.is_adult(20)) # 输出: True
抽象基类与接口
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
# 无法实例化抽象类
# shape = Shape() # 报错: TypeError
circle = Circle(5)
print(circle.area()) # 输出: 78.5
面向对象设计原则
- 单一职责原则:一个类只负责一项职责。
- 开放封闭原则:对扩展开放,对修改封闭。
- 里氏替换原则:子类可以替换父类而不影响程序。
- 接口隔离原则:使用多个专门接口,而不是单一总接口。
- 依赖倒置原则:高层模块不依赖低层模块,二者都依赖抽象。
2.继承与多态
继承(Inheritance)
继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码复用和层次化设计。
单继承
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} makes a sound.")
class Dog(Animal):
def speak(self): # 方法重写(Override)
print(f"{self.name} barks.")
# 创建对象
dog = Dog("Buddy")
dog.speak() # 输出: Buddy barks.
访问父类方法
使用super()
调用父类方法:
class Cat(Animal):
def speak(self):
super().speak() # 调用父类的speak()
print(f"{self.name} meows.")
cat = Cat("Whiskers")
cat.speak()
# 输出:
# Whiskers makes a sound.
# Whiskers meows.
多重继承
一个子类可以继承多个父类:
class Flyable:
def fly(self):
print("I can fly!")
class Swimmable:
def swim(self):
print("I can swim!")
class Duck(Flyable, Swimmable):
pass
duck = Duck()
duck.fly() # 输出: I can fly!
duck.swim() # 输出: I can swim!
多态(Polymorphism)
多态允许不同类的对象通过相同接口调用方法,实现 "一种接口,多种实现"。
方法重写(Override)
子类重新实现父类的方法:
class Shape:
def area(self):
return 0
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self): # 重写area方法
return 3.14 * self.radius ** 2
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self): # 重写area方法
return self.side ** 2
# 多态示例
shapes = [Circle(5), Square(4)]
for shape in shapes:
print(shape.area()) # 自动调用对应子类的area方法
鸭子类型(Duck Typing)
不关注对象的类型,只关注对象是否实现了特定方法:
class Bird:
def fly(self):
print("Bird flies")
class Airplane:
def fly(self):
print("Airplane flies")
def let_it_fly(obj):
obj.fly() # 只要obj有fly()方法即可调用
bird = Bird()
plane = Airplane()
let_it_fly(bird) # 输出: Bird flies
let_it_fly(plane) # 输出: Airplane flies
抽象基类(ABC)
用于定义接口(抽象方法),强制子类实现特定方法:
from abc import ABC, abstractmethod
class Animal(ABC): # 抽象基类
@abstractmethod # 抽象方法,子类必须实现
def speak(self):
pass
class Dog(Animal):
def speak(self): # 必须实现speak方法
print("Woof!")
# 无法实例化抽象类
# animal = Animal() # 报错: TypeError
dog = Dog()
dog.speak() # 输出: Woof!
MRO(方法解析顺序)
多重继承时,Python 通过 C3 线性化算法确定方法调用顺序:
class A:
def method(self):
print("A's method")
class B(A):
def method(self):
print("B's method")
class C(A):
def method(self):
print("C's method")
class D(B, C): # 继承顺序为B→C
pass
d = D()
d.method() # 输出: B's method
print(D.mro()) # 查看MRO顺序
# 输出: [D, B, C, A, object]
应用场景
代码复用
通过继承提取公共代码到父类,减少重复:
class Vehicle:
def __init__(self, brand):
self.brand = brand
def start(self):
print(f"{self.brand} starts.")
class Car(Vehicle):
pass
class Motorcycle(Vehicle):
pass
框架设计
例如 Django 框架中的视图类:
from django.views import View
class MyView(View):
def get(self, request):
return HttpResponse("Hello, World!")
策略模式
通过多态实现不同算法的切换:
class PaymentStrategy:
def pay(self, amount):
pass
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying {amount} via Credit Card")
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying {amount} via PayPal")
# 使用策略
strategy = CreditCardPayment()
strategy.pay(100) # 输出: Paying 100 via Credit Card
注意事项
- 避免过度继承:多层继承会导致代码复杂,优先使用组合(Composition)。
- 钻石问题:多重继承可能导致方法调用歧义,通过合理设计 MRO 或使用 Mixins 解决。
- 抽象基类的使用:当需要强制接口实现时,使用
abc.ABC
和@abstractmethod
。
3.封装与抽象
封装(Encapsulation)
封装是将数据(属性)和操作数据的方法绑定在一起,并隐藏内部实现细节的机制。通过访问控制,限制外部直接访问对象的属性。
访问控制
Python 通过命名约定实现封装:
- 公有属性 / 方法:无特殊前缀(如
name
) - 受保护属性 / 方法:单下划线前缀(如
_age
) - 私有属性 / 方法:双下划线前缀(如
__salary
)
class Employee:
def __init__(self, name, age, salary):
self.name = name # 公有属性
self._age = age # 受保护属性
self.__salary = salary # 私有属性
def get_salary(self): # 公有方法
return self.__salary
def _calculate_bonus(self): # 受保护方法
return self.__salary * 0.1
def __display_private(self):# 私有方法
print(f"Private data: {self.__salary}")
# 使用封装
emp = Employee("Alice", 30, 5000)
# 可以访问公有属性
print(emp.name) # 输出: Alice
# 可以访问受保护属性(但不建议)
print(emp._age) # 输出: 30
# 无法直接访问私有属性
# print(emp.__salary) # 报错: AttributeError
# 可以通过公有方法访问私有属性
print(emp.get_salary()) # 输出: 5000
# 私有方法名称被混淆
# emp.__display_private() # 报错: AttributeError
属性封装(Property)
使用@property
装饰器实现属性的封装与验证:
class Person:
def __init__(self, age):
self._age = age # 私有属性
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("Age cannot be negative")
self._age = value
# 使用属性封装
p = Person(25)
print(p.age) # 调用@property方法
p.age = 30 # 调用@age.setter方法
# p.age = -5 # 抛出ValueError
抽象(Abstraction)
抽象是提取事物的共性,忽略细节,只关注接口而不关注具体实现的机制。Python 通过抽象基类(ABC)和抽象方法实现。
抽象基类(ABC)
from abc import ABC, abstractmethod
class Shape(ABC): # 抽象基类
@abstractmethod # 抽象方法(必须由子类实现)
def area(self):
pass
def describe(self): # 普通方法(子类继承)
return "This is a shape."
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self): # 实现抽象方法
return 3.14 * self.radius ** 2
# 无法实例化抽象类
# shape = Shape() # 报错: TypeError
circle = Circle(5)
print(circle.area()) # 输出: 78.5
print(circle.describe()) # 输出: This is a shape.
抽象属性
from abc import ABC, abstractproperty
class Animal(ABC):
@abstractproperty # 抽象属性
def sound(self):
pass
class Dog(Animal):
@property
def sound(self): # 实现抽象属性
return "Woof!"
dog = Dog()
print(dog.sound) # 输出: Woof!
封装与抽象的对比
特性 | 封装 | 抽象 |
---|---|---|
核心目标 | 隐藏实现细节,保护数据 | 提取共性,定义接口 |
实现方式 | 访问控制(命名约定) | 抽象基类(ABC)和抽象方法 |
使用者视角 | 无需关心内部实现 | 只需遵循接口规范 |
应用场景 | 类的内部数据保护 | 框架设计、多态实现 |
应用场景
封装的应用
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有属性
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return True
return False
@property
def balance(self): # 只读属性
return self.__balance
# 使用封装
account = BankAccount(1000)
account.deposit(500)
account.withdraw(200)
print(account.balance) # 输出: 1300
抽象的应用(框架设计)
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def process_payment(self, amount):
pass
class CreditCardProcessor(PaymentProcessor):
def process_payment(self, amount):
print(f"Processing credit card payment: ${amount}")
class PayPalProcessor(PaymentProcessor):
def process_payment(self, amount):
print(f"Processing PayPal payment: ${amount}")
# 使用抽象接口
def pay(order_amount, processor):
processor.process_payment(order_amount)
credit_card = CreditCardProcessor()
paypal = PayPalProcessor()
pay(100, credit_card) # 输出: Processing credit card payment: $100
pay(200, paypal) # 输出: Processing PayPal payment: $200
最佳实践
-
封装原则:
- 将敏感数据设为私有属性
- 通过公有方法提供访问接口
- 使用
@property
装饰器简化属性访问
-
抽象原则:
- 使用抽象基类定义接口规范
- 强制子类实现必要方法
- 避免创建具体实例(通过
ABC
和@abstractmethod
约束)
-
结合使用:
- 抽象基类定义接口,具体子类实现并封装细节
- 利用多态实现灵活调用
4.特殊方法与运算符重载
特殊方法概述
特殊方法(也称魔术方法)是 Python 中预先定义的、以双下划线开头和结尾的方法(如__init__
、__str__
)。它们用于实现对象的内置行为,如运算符重载、类型转换、容器协议等。
常用特殊方法分类
对象创建与销毁
class MyClass:
def __new__(cls, *args, **kwargs):
# 对象创建时调用(先于__init__)
print("Creating instance...")
return super().__new__(cls)
def __init__(self, value):
# 对象初始化
self.value = value
def __del__(self):
# 对象销毁时调用
print("Instance deleted.")
obj = MyClass(42) # 输出: Creating instance...
del obj # 输出: Instance deleted.
字符串表示
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
# 用于print()和str()
return f"Point({self.x}, {self.y})"
def __repr__(self):
# 用于调试和交互式环境
return f"Point({self.x}, {self.y}) (repr)"
p = Point(3, 4)
print(p) # 输出: Point(3, 4)
print(repr(p)) # 输出: Point(3, 4) (repr)
运算符重载
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
# 重载加法运算符
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
# 重载减法运算符
return Vector(self.x - other.x, self.y - other.y)
def __eq__(self, other):
# 重载相等比较
return self.x == other.x and self.y == other.y
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2 # 调用__add__
print(v3.x, v3.y) # 输出: 4 6
print(v1 == v2) # 调用__eq__,输出: False
容器协议
class MyList:
def __init__(self):
self.data = []
def __len__(self):
# 支持len()
return len(self.data)
def __getitem__(self, index):
# 支持索引访问
return self.data[index]
def __setitem__(self, index, value):
# 支持索引赋值
self.data[index] = value
def __contains__(self, value):
# 支持in操作符
return value in self.data
my_list = MyList()
my_list.data = [1, 2, 3]
print(len(my_list)) # 输出: 3
print(my_list[0]) # 输出: 1
my_list[0] = 100 # 调用__setitem__
print(2 in my_list) # 调用__contains__,输出: True
类型转换
class Number:
def __init__(self, value):
self.value = value
def __int__(self):
# 转换为整数
return int(self.value)
def __float__(self):
# 转换为浮点数
return float(self.value)
def __bool__(self):
# 转换为布尔值
return self.value != 0
num = Number(42)
print(int(num)) # 输出: 42
print(float(num)) # 输出: 42.0
print(bool(num)) # 输出: True
运算符重载详解
Python 允许通过特殊方法重载常见的运算符,使自定义对象具有更自然的行为。
算术运算符
class Money:
def __init__(self, amount, currency):
self.amount = amount
self.currency = currency
def __add__(self, other):
# 加法重载
if self.currency == other.currency:
return Money(self.amount + other.amount, self.currency)
raise ValueError("Currency mismatch")
def __sub__(self, other):
# 减法重载
if self.currency == other.currency:
return Money(self.amount - other.amount, self.currency)
raise ValueError("Currency mismatch")
def __mul__(self, scalar):
# 乘法重载(与标量相乘)
return Money(self.amount * scalar, self.currency)
def __rmul__(self, scalar):
# 反向乘法(当标量在左侧时调用)
return self * scalar
usd1 = Money(100, "USD")
usd2 = Money(200, "USD")
result = usd1 + usd2
print(result.amount, result.currency) # 输出: 300 USD
result = usd1 * 2
print(result.amount) # 输出: 200
result = 3 * usd1 # 调用__rmul__
print(result.amount) # 输出: 300
比较运算符
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
# 等于(==)
return self.age == other.age
def __lt__(self, other):
# 小于(<)
return self.age < other.age
def __le__(self, other):
# 小于等于(<=)
return self.age <= other.age
p1 = Person("Alice", 25)
p2 = Person("Bob", 30)
print(p1 == p2) # 输出: False
print(p1 < p2) # 输出: True
print(p1 <= p2) # 输出: True
一元运算符
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __neg__(self):
# 负号(-)
return Point(-self.x, -self.y)
def __abs__(self):
# 绝对值(abs())
return Point(abs(self.x), abs(self.y))
p = Point(-3, 4)
print((-p).x) # 输出: 3
print(abs(p).y) # 输出: 4
容器相关特殊方法
序列协议
class MySequence:
def __init__(self, *items):
self.items = list(items)
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, value):
self.items[index] = value
seq = MySequence(1, 2, 3)
print(len(seq)) # 输出: 3
print(seq[1]) # 输出: 2
seq[1] = 200 # 修改元素
print(seq[1]) # 输出: 200
迭代器协议
class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
# 返回迭代器对象
self.current = self.start
return self
def __next__(self):
# 返回下一个值
if self.current <= 0:
raise StopIteration
value = self.current
self.current -= 1
return value
for num in Countdown(3):
print(num) # 输出: 3 2 1
应用场景
- 数学类库:实现向量、矩阵等运算
- 自定义容器:创建类似列表、字典的对象
- DSL(领域特定语言):使代码更具可读性
- 框架设计:如 Django 的 ORM 查询语法
# 示例:自定义时间间隔类
class TimeInterval:
def __init__(self, hours=0, minutes=0, seconds=0):
self.total_seconds = hours * 3600 + minutes * 60 + seconds
def __add__(self, other):
return TimeInterval(seconds=self.total_seconds + other.total_seconds)
def __str__(self):
hours, remainder = divmod(self.total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{hours}h {minutes}m {seconds}s"
t1 = TimeInterval(hours=1, minutes=30)
t2 = TimeInterval(minutes=45, seconds=30)
total = t1 + t2
print(total) # 输出: 2h 15m 30s
注意事项
- 保持一致性:重载运算符时应遵循内置类型的行为规范
- 避免滥用:仅在符合直觉的场景下使用
- 反向运算符:实现
__radd__
等方法处理混合类型运算 - 不可变对象:算术运算符应返回新对象而非修改自身
四、文件操作与数据处理
1.文件读写
文件打开与关闭
使用open()
函数打开文件,返回文件对象,使用后需调用close()
关闭。
# 打开文件
file = open("example.txt", "r") # 以只读模式打开
# 读取文件内容
content = file.read()
print(content)
# 关闭文件
file.close()
更安全的做法是使用with
语句(自动管理资源):
with open("example.txt", "r") as file:
content = file.read()
print(content)
# 文件会在此处自动关闭
文件打开模式
模式 | 描述 |
---|---|
r |
只读(默认) |
w |
写入(覆盖原有内容,文件不存在则创建) |
a |
追加(文件不存在则创建) |
x |
独占创建(文件已存在则报错) |
b |
二进制模式 |
t |
文本模式(默认) |
+ |
读写模式 |
示例:
# 写入二进制文件
with open("data.bin", "wb") as file:
file.write(b"Hello, World!")
# 以读写模式打开文件
with open("example.txt", "r+") as file:
content = file.read()
file.write("New content")
读取文件内容
读取整个文件
with open("example.txt", "r") as file:
content = file.read() # 读取全部内容为字符串
print(content)
逐行读取
with open("example.txt", "r") as file:
for line in file: # 逐行迭代
print(line.strip()) # 去除行末换行符
读取所有行到列表
with open("example.txt", "r") as file:
lines = file.readlines() # 返回包含所有行的列表
for line in lines:
print(line)