Python 基础教程

Python 基础教程

Python 是一种简单易学、功能强大的编程语言,由 Guido van Rossum 于 1991 年发布。它以清晰的语法和丰富的生态著称,广泛应用于 Web 开发、数据分析、人工智能、自动化脚本等领域。

本教程内容

本教程从 Python 的简介与环境搭建讲起,系统覆盖:基础语法、变量与数据类型、运算符、条件与循环、数字/字符串/列表/元组/字典、函数、模块、文件操作、异常处理、面向对象、正则表达式、网络编程、多线程,以及 JSON、MySQL、GUI 等应用主题。

Python 的特点

  • 语法简洁:缩进即代码块,可读性强
  • 解释执行:无需编译,即写即跑
  • 动态类型:变量无需声明类型
  • 丰富的标准库与第三方生态
  • 跨平台:Windows / macOS / Linux
  • 胶水语言:易与其他语言集成

版本说明

Python 2 已于 2020 年停止维护,新项目请使用 Python 3。本教程内容以 Python 3 为主,同时介绍 2.x 与 3.x 的主要区别。

学习建议

动手实践是学习编程的关键:每章代码亲自运行,配合课后练习。多写多改,理解会更深。

Python 简介

Python 简介

Python 是一门高级、解释型、通用编程语言,以其简洁优雅的语法和"开箱即用"的标准库深受开发者喜爱。

历史

  • 1989 年:Guido van Rossum 开始设计 Python
  • 1991 年:第一个公开版本发布
  • 2000 年:Python 2.0
  • 2008 年:Python 3.0(不兼容 2.x 的重大升级)
  • 2020 年:Python 2 正式停止维护

能做什么

  • Web 开发:Django、Flask、FastAPI
  • 数据分析:NumPy、Pandas、Matplotlib
  • 人工智能:PyTorch、TensorFlow、scikit-learn
  • 自动化:脚本、爬虫、运维工具
  • 科学计算:SciPy、SymPy
  • 桌面应用:Tkinter、PyQt

Hello World

print("Hello, Python!")

# 输出: Hello, Python!

为什么选择 Python

  • 学习曲线平缓,适合入门
  • 代码量少,开发效率高
  • 社区庞大,问题容易找到答案
  • AI 时代的首选语言之一

运行方式

# 方式1: 交互式解释器
python

# 方式2: 运行脚本文件
python hello.py

# 方式3: 直接执行代码字符串
python -c "print('hi')"

Python 环境搭建

Python 环境搭建

开始 Python 编程前,需要安装 Python 解释器并配置开发环境。本节介绍各平台的安装方法。

Windows 安装

# 1. 访问 python.org 下载 Windows 安装包
# 2. 勾选 "Add Python to PATH"(重要!)
# 3. 点击 Install Now

# 验证
python --version

macOS 安装

# 方式1: 官方安装包
# 方式2: Homebrew(推荐)
brew install python

# 验证
python3 --version

Linux 安装

# Debian/Ubuntu
sudo apt update
sudo apt install python3 python3-pip

# CentOS/RHEL
sudo yum install python3

包管理 pip

# 安装包
pip install requests

# 指定版本
pip install numpy==1.26.4

# 查看已安装
pip list

# 卸载
pip uninstall requests

# 国内镜像加速
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

虚拟环境(推荐)

# 创建虚拟环境(隔离项目依赖)
python -m venv myenv

# 激活
# Windows
myenv\Scripts\activate
# macOS/Linux
source myenv/bin/activate

# 退出
deactivate

# 或用 conda(科学计算常用)
conda create -n myenv python=3.11
conda activate myenv

开发工具

# 推荐编辑器/IDE:
# - VS Code + Python 扩展(轻量推荐)
# - PyCharm(功能全)
# - Jupyter Notebook(数据分析)
# - IDLE(自带,入门)

# VS Code 插件:
# Python, Pylance, Jupyter

验证环境

python --version
pip --version

# 运行第一个程序
python -c "print('环境就绪!')"

环境就绪后,就可以开始学习 Python 基础语法了。

Python 基础语法

Python 基础语法

Python 语法以简洁著称:缩进定义代码块、无需分号、无需声明类型。本节快速浏览核心语法。

注释

# 单行注释

"""
多行注释(用三引号)
或文档字符串
"""

缩进与代码块

# Python 用缩进(通常 4 空格)表示代码块
if x > 0:
    print("正数")        # 缩进的代码属于 if
    print("继续")
print("无条件执行")       # 不缩进,独立

# 不要混用 Tab 与空格(报错!)

变量与赋值

name = "Python"     # 字符串
age = 30            # 整数
pi = 3.14           # 浮点
ok = True           # 布尔
tags = ["a", "b"]   # 列表

# 动态类型:无需声明
# 变量可重新赋不同类型的值
x = 1
x = "现在是字符串"

输入输出

# 输出
print("Hello")
print("值:", 42)
print(f"格式化: {name} 年龄 {age}")   # f-string
print("拼接", "多个", "参数")

# 输入
name = input("请输入名字: ")
print(f"你好, {name}")

常用内建函数

len("abc")        # 长度 3
type(123)         # <class 'int'>
int("42")         # 转整数
float("3.14")     # 转浮点
str(123)          # 转字符串
list("abc")       # ['a', 'b', 'c']
range(5)          # 0..4
sum([1,2,3])      # 6
max(1,5,3)        # 5
abs(-5)           # 5

标识符规则

# 命名规则:
# - 字母/数字/下划线组成,不能数字开头
# - 区分大小写(Name 与 name 不同)
# - 关键字不可作变量名(if, for, class 等)

# 命名约定:
# - 变量/函数: snake_case(my_name)
# - 类: PascalCase(MyClass)
# - 常量: ALL_CAPS(MAX_SIZE)

多行与续行

# 长表达式可用括号换行
total = (1 + 2 + 3
         + 4 + 5)

# 或反斜杠续行
total = 1 + 2 + \
        3 + 4

Python 语法重在"可读性":缩进即结构。养成 4 空格缩进、snake_case 命名的习惯,代码自然清晰。

Python 变量类型

Python 变量类型

Python 是动态类型语言,变量可以指向任意类型的对象。本节介绍 Python 的内置数据类型。

基本类型

# 数字
x = 10           # int 整数
y = 3.14         # float 浮点
z = 2 + 3j       # complex 复数

# 布尔
t = True
f = False

# 字符串
s = "hello"
s2 = 'world'

# 空值
nothing = None

容器类型

# 列表(有序,可变)
lst = [1, 2, 3]
lst.append(4)          # [1,2,3,4]

# 元组(有序,不可变)
tup = (1, 2, 3)
# tup[0] = 9  → 报错

# 字典(键值对)
d = {"name": "Python", "age": 30}
d["version"] = "3.11"

# 集合(无序,去重)
s = {1, 2, 2, 3}       # {1, 2, 3}

类型检查与转换

type(x)          # <class 'int'>
isinstance(x, int)   # True

# 转换
int("42")        # 字符串 → 整数
float(1)         # 整数 → 浮点
str(3.14)        # → 字符串
bool(0)          # False
list((1,2))      # 元组 → 列表
tuple([1,2])     # 列表 → 元组

可变与不可变

# 不可变(immutable): 修改产生新对象
# 数字、字符串、元组
s = "abc"
s2 = s.upper()    # s 不变,产生 "ABC"

# 可变(mutable): 原地修改
# 列表、字典、集合
lst = [1, 2]
lst.append(3)     # 原对象被修改

# 注意: 可变对象作为默认参数/共享引用时的坑

变量的内存模型

# 变量是"引用"(指向对象的标签)
a = [1, 2, 3]
b = a             # b 和 a 指向同一列表!
b.append(4)
print(a)          # [1,2,3,4] ← a 也变了!

# 复制需要显式
c = a.copy()      # 浅拷贝
import copy
d = copy.deepcopy(a)   # 深拷贝

序列通用操作

s = "hello"
lst = [1, 2, 3]

len(s)           # 长度
s[0]             # 索引 'h'
s[-1]            # 负索引 'o'
lst[1:3]         # 切片 [2, 3]
lst[::2]         # 步长 [1, 3]
"ell" in s       # 成员判断 True
s + "!"          # 拼接
[0] * 3          # 重复 [0,0,0]

类型选择指南

# 场景 → 类型
# 有序可变集合  → list
# 有序不可变    → tuple
# 键值映射      → dict
# 去重/集合运算  → set
# 单值          → int/float/str/bool

# 选择原则: 用最合适的类型表达数据
# 让代码更清晰、更不易出错

掌握内置类型与"可变/不可变"、"引用/复制"这两个概念,是写出正确 Python 代码的基础。

Python 运算符

Python 运算符

运算符是表达计算的符号。Python 支持算术、比较、逻辑、赋值、成员、身份等运算符。

算术运算符

a, b = 10, 3
a + b     # 13 加
a - b     # 7  减
a * b     # 30 乘
a / b     # 3.333 除(结果为浮点)
a // b    # 3  整除(取商)
a % b     # 1  取余
a ** b    # 1000 幂

# 注意:
7 / 2      # 3.5 (Python3 除法总是浮点)
7 // 2     # 3

比较运算符

1 == 1     # True  等于
1 != 2     # True  不等
2 > 1      # True
1 < 2      # True
1 <= 1     # True
2 >= 3     # False

# 链式比较
1 < x < 10      # x 在 1 和 10 之间

# 注意: == 比较值,is 比较身份
a = [1]
b = [1]
a == b     # True(值相同)
a is b     # False(不同对象)

逻辑运算符

True and False    # False
True or False     # True
not True          # False

# 短路求值
x = 0 or "默认"    # "默认"(or 返回第一个真值)
y = 5 and 10       # 10(and 返回最后一个真值)

# 真值判断
# False、0、空字符串、空容器 为假
if not []:        # 空列表为假
    print("空列表")

# 推荐写法
if value:         # 而非 if value == True
if not items:     # 而非 if len(items) == 0

赋值运算符

x = 5
x += 3       # x = 8
x -= 2       # 6
x *= 4       # 24
x /= 3       # 8.0
x //= 2      # 4
x %= 3       # 1
x **= 2      # 1

# 多变量赋值
a = b = c = 0        # 都赋 0
x, y = 1, 2          # 分别赋值
x, y = y, x          # 交换(经典!)

成员与身份运算符

# 成员
"a" in "abc"          # True
3 in [1, 2, 3]        # True
"k" in {"k": 1}       # True(字典查键)
5 not in [1, 2]       # True

# 身份
a = None
a is None             # True(常用!)
a is not None         # False

位运算符

# 二进制运算(较少用,了解即可)
5 & 3      # 1  按位与 (101 & 011 = 001)
5 | 3      # 7  按位或 (101 | 011 = 111)
5 ^ 3      # 6  按位异或
~5         # -6 按位取反
5 << 1     # 10 左移(×2)
5 >> 1     # 2  右移(÷2)

运算符优先级

# 从高到低(常用部分):
# ** 幂
# +x, -x, ~x 一元
# *, /, //, %
# +, - 二元
# <<, >> 位移
# & | ^ 位运算
# ==, !=, >, < ... 比较
# not and or 逻辑(从高到低: not > and > or)

# 建议: 复杂表达式加括号,清晰优先
result = (a + b) * c - (d if cond else e)

运算符是计算的"词汇"。重点掌握算术、比较、逻辑与赋值,理解真值判断与短路求值,日常开发足够。

Python 条件语句

Python 条件语句

条件语句让程序根据条件执行不同分支。Python 用 if/elif/else 表达分支逻辑。

if 基本结构

age = 18
if age >= 18:
    print("成年")
# 输出: 成年

if / else

score = 55
if score >= 60:
    print("及格")
else:
    print("不及格")
# 输出: 不及格

if / elif / else

score = 85
if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
elif score >= 60:
    grade = "D"
else:
    grade = "F"
print(grade)    # B

# elif 可写多个,自上而下匹配第一个真值

嵌套条件

user = "admin"
logged_in = True

if logged_in:
    if user == "admin":
        print("管理员页面")
    else:
        print("普通用户页面")
else:
    print("请先登录")

# 建议: 嵌套过深时用逻辑合并
if logged_in and user == "admin":
    print("管理员页面")

三元表达式

# 简洁的单行条件
x = 10
result = "大" if x > 5 else "小"
print(result)    # 大

# 等价写法
if x > 5:
    result = "大"
else:
    result = "小"

真值判断

# Python 的真值规则:
# 假: False, None, 0, "", [], {}, set()
# 真: 其余一切

# 推荐写法(简洁)
name = ""
if not name:              # 等价 if name == ""
    name = "匿名"

items = [1, 2]
if items:                 # 等价 if len(items) > 0
    print(f"{len(items)} 项")

match-case(Python 3.10+)

# 模式匹配(类似 switch)
def describe(value):
    match value:
        case 0:
            return "零"
        case 1 | 2:
            return "小数字"
        case [x, y]:
            return f"列表: {x},{y}"
        case {"name": n}:
            return f"名字: {n}"
        case _:
            return "其他"

print(describe(1))       # 小数字
print(describe([1, 2]))  # 列表: 1,2

条件语句最佳实践

# 1. 先处理简单/异常情况(早返回)
def process(data):
    if not data:
        return "空数据"       # 早返回
    # 主逻辑...

# 2. 避免深层嵌套,用逻辑合并或提前返回
# 3. 条件表达式保持可读,复杂逻辑提取为函数
# 4. 用真值判断代替显式比较

# 示例: 守卫子句风格
def login(user, pwd):
    if not user:
        return "用户名为空"
    if not pwd:
        return "密码为空"
    # 验证逻辑...
    return "成功"

条件语句是程序逻辑的核心。掌握 if/elif/else、三元表达式与真值判断,配合"早返回"风格,分支逻辑清晰易读。

Python 循环语句

Python 循环语句

循环用于重复执行代码。Python 提供 for 与 while 两种循环,配合 range、break、continue 使用。

for 循环

# 遍历序列
for fruit in ["苹果", "香蕉", "橘子"]:
    print(fruit)

# 遍历字符串
for ch in "Python":
    print(ch)

# 遍历字典
d = {"a": 1, "b": 2}
for key in d:            # 键
    print(key)
for key, value in d.items():   # 键值
    print(key, value)

range 与 for

# range(开始, 结束, 步长), 不含结束
for i in range(5):       # 0,1,2,3,4
    print(i)

for i in range(2, 6):    # 2,3,4,5
    print(i)

for i in range(0, 10, 2):  # 0,2,4,6,8
    print(i)

for i in range(5, 0, -1):  # 5,4,3,2,1
    print(i)

# 带索引遍历
names = ["a", "b"]
for idx, name in enumerate(names, start=1):
    print(idx, name)

while 循环

# 条件为真时循环
count = 0
while count < 5:
    print(count)
    count += 1

# 无限循环 + 退出条件
while True:
    cmd = input("命令(q 退出): ")
    if cmd == "q":
        break
    print(f"执行: {cmd}")

break / continue / else

# break: 立即退出循环
for i in range(10):
    if i == 5:
        break
    print(i)       # 0-4

# continue: 跳过本次循环
for i in range(5):
    if i == 2:
        continue
    print(i)       # 0,1,3,4

# for-else: 循环正常结束(未被 break)时执行
for i in range(5):
    if i == 3:
        break
else:
    print("循环完整执行(无 break)")   # 不会执行

# else 常用于"查找失败"场景
for item in items:
    if item == target:
        print("找到了")
        break
else:
    print("未找到")

循环嵌套

# 九九乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}x{i}={i*j}", end="\t")
    print()   # 换行

# 嵌套注意: 内层 break 只退出内层循环

列表推导式(循环的优雅替代)

# 生成列表
squares = [i ** 2 for i in range(5)]     # [0,1,4,9,16]

# 带条件
evens = [x for x in range(10) if x % 2 == 0]  # [0,2,4,6,8]

# 双重循环
pairs = [(x, y) for x in range(3) for y in range(2)]

# 字典/集合推导
d = {x: x * 2 for x in range(3)}   # {0:0, 1:2, 2:4}
s = {x for x in "abcabc"}          # {'a','b','c'}

循环最佳实践

# 1. 优先 for(可读性)而非 while
# 2. 用 enumerate 代替手动索引
# 3. 推导式简洁,但嵌套过深时用普通循环
# 4. 避免死循环: while 条件保证会变假
# 5. 大数据用迭代器(不全部载入内存)
for line in open("big.txt"):   # 逐行读
    process(line)

循环是程序"重复劳动"的武器。for + range 覆盖 90% 场景,推导式让生成列表更优雅,break/continue 精确控制流程。

Python While 循环语句

Python While 循环语句

while 循环在条件为真时重复执行代码块,适合"不确定次数"的循环场景。

基本语法

count = 0
while count < 5:
    print(f"第 {count} 次")
    count += 1
# 输出 0-4

典型场景

# 1. 用户输入循环(直到合法)
while True:
    age = input("年龄: ")
    if age.isdigit():
        break
    print("请输入数字!")

# 2. 重试机制
attempts = 0
while attempts < 3:
    attempts += 1
    if login():
        print("登录成功")
        break
    print(f"失败, 剩余 {3 - attempts} 次")

# 3. 消费队列/生成器
while queue:
    item = queue.pop()
    process(item)

# 4. 条件满足前等待
while not server_ready():
    time.sleep(1)

while / else

# 条件变假(未 break)时执行 else
n = 5
while n > 0:
    n -= 1
    if n == 3:
        break
else:
    print("循环正常结束")    # 被 break 了,不执行

# 典型: 超时检测
timeout = 10
while timeout > 0:
    if check():
        print("成功")
        break
    timeout -= 1
else:
    print("超时失败")

死循环与退出

# 死循环(配合 break 使用)
while True:
    cmd = input("> ")
    if cmd == "exit":
        break
    if cmd == "skip":
        continue
    print(f"执行 {cmd}")

# 注意:
# - Ctrl+C 中断死循环
# - 确保循环内条件最终变化,避免真死循环
# - 用 break 显式退出比标志位更清晰

# 标志位方式(较少用)
running = True
while running:
    ...
    if done:
        running = False

与 for 的选择

# for: 遍历已知集合(次数确定)
for x in items: ...

# while: 条件驱动(次数不确定)
while condition: ...

# 经验法则:
# 能 for 就 for(更清晰)
# 需要条件循环/无限循环用 while

# 例: 猜数字游戏
import random
secret = random.randint(1, 100)
guess = None
while guess != secret:
    guess = int(input("猜 1-100: "))
    if guess > secret:
        print("大了")
    elif guess < secret:
        print("小了")
print(f"猜对了!答案是 {secret}")

嵌套 while

# 打印 3x3 矩阵位置
i = 0
while i < 3:
    j = 0
    while j < 3:
        print(f"({i},{j})", end=" ")
        j += 1
    print()
    i += 1

# 内层 break 只退出内层
# 需要同时退出时用标志位或函数 return

常见错误

# 1. 忘记更新条件变量 → 死循环
i = 0
while i < 5:
    print(i)
    # 缺少 i += 1 → 死循环!

# 2. 条件写反
# 3. 浮点比较的精度问题
x = 0.0
while x != 1.0:      # 危险!浮点不精确
    x += 0.1
# 应改为: while x < 1.0 - 1e-9

while 循环适合"条件驱动"的场景:用户交互、重试、轮询。配合 break/continue/else,控制流完整而清晰。

Python for 循环语句

Python for 循环语句

for 循环是 Python 最常用的循环:遍历任何可迭代对象(列表、元组、字符串、字典、集合、range、生成器)。

遍历各类对象

# 列表
for x in [1, 2, 3]: print(x)

# 元组
for x in (1, 2, 3): print(x)

# 字符串
for ch in "abc": print(ch)

# 字典
for k in d: print(k)              # 键
for v in d.values(): print(v)     # 值
for k, v in d.items(): print(k, v)  # 键值

# 集合
for x in {1, 2, 3}: print(x)      # 无序

# 文件(逐行)
for line in open("file.txt"):
    print(line, end="")

range 迭代

# 指定次数
for _ in range(5):      # _ 表示不需要变量
    do_something()

# 带索引
for i in range(len(items)):
    print(i, items[i])

# 推荐: enumerate
for i, item in enumerate(items):
    print(i, item)

# 反向/步长
for i in range(10, 0, -2):    # 10,8,6,4,2
    print(i)

并行遍历 zip

names = ["张三", "李四", "王五"]
scores = [90, 85, 95]

# 同时遍历多个序列
for name, score in zip(names, scores):
    print(f"{name}: {score}")

# zip 以最短序列为准
# 需要以最长为准: itertools.zip_longest
from itertools import zip_longest
for a, b in zip_longest([1,2,3], [4,5], fillvalue=0):
    print(a, b)     # (1,4)(2,5)(3,0)

循环控制

for i in range(10):
    if i == 3:
        continue        # 跳过
    if i == 8:
        break           # 退出
    print(i)            # 0,1,2,4,5,6,7

# for-else: 未 break 时执行
for i in range(5):
    if i == 10:         # 永不触发
        break
else:
    print("完整遍历")    # 执行

解包遍历

# 列表元素是元组时解包
points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
    print(f"x={x}, y={y}")

# 嵌套解包
data = [(1, "a", True), (2, "b", False)]
for num, char, flag in data:
    print(num, char, flag)

# 解包部分(用 _ 忽略)
for _, name, _ in data:
    print(name)

迭代器与生成器

# for 本质: 调用 iter() 得到迭代器,反复 next()
# 直到 StopIteration

# 自定义迭代器
class CountDown:
    def __init__(self, n):
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.n <= 0:
            raise StopIteration
        self.n -= 1
        return self.n + 1

for x in CountDown(3):
    print(x)     # 3, 2, 1

# 生成器(推荐)
def countdown(n):
    while n > 0:
        yield n
        n -= 1

for x in countdown(3):
    print(x)     # 3, 2, 1

性能注意

# 1. 避免在循环内重复计算
# ❌
for x in items:
    y = len(items) + x     # len 每次算
# ✅
n = len(items)
for x in items:
    y = n + x

# 2. 用推导式代替 append 循环(更快)
# 3. 大文件/大数据用生成器(省内存)
# 4. 循环内尽量少做 IO

# 5. 用内置函数替代手写循环
sum(items)              # 替代循环求和
max(items) / min(items)
any(x > 5 for x in items)   # 是否存在
all(x > 0 for x in items)   # 是否全部

for 循环是 Python 的"瑞士军刀":遍历一切可迭代对象,配合 enumerate/zip/推导式,代码既简洁又高效。

Python 循环嵌套

Python 循环嵌套

循环嵌套是一个循环体内包含另一个循环,用于处理多维结构:矩阵、表格、组合、金字塔等。

基本嵌套

# 外层循环每执行一次,内层完整执行一轮
for i in range(3):          # 外层
    for j in range(2):      # 内层
        print(f"i={i}, j={j}")
    print("---")

# 输出顺序:
# i=0: j=0, j=1
# i=1: j=0, j=1
# i=2: j=0, j=1

矩形与三角形

# 打印 3x5 矩形
for i in range(3):
    for j in range(5):
        print("*", end="")
    print()
# *****
# *****
# *****

# 直角三角形
for i in range(1, 6):
    for j in range(i):
        print("*", end="")
    print()
# *
# **
# ***

# 九九乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}x{i}={i*j}", end="\t")
    print()

遍历二维列表

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

# 遍历所有元素
for row in matrix:
    for value in row:
        print(value, end=" ")
    print()
# 1 2 3
# 4 5 6
# 7 8 9

# 带索引
for i, row in enumerate(matrix):
    for j, value in enumerate(row):
        if value == 5:
            print(f"5 在 ({i}, {j})")

组合生成

# 生成坐标对
points = []
for x in range(3):
    for y in range(3):
        points.append((x, y))
# [(0,0),(0,1),(0,2),(1,0),...]

# 等价推导式
points = [(x, y) for x in range(3) for y in range(3)]

# 筛选组合(去重/条件)
pairs = [(a, b) for a in range(1, 5)
         for b in range(1, 5) if a < b]
# [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]

break 在嵌套中的作用

# 内层 break 只退出内层循环!
for i in range(3):
    for j in range(5):
        if j == 2:
            break          # 只退出内层
        print(j, end="")
    print()   # 每次输出 "01"

提前退出所有层

# 方式1: 标志位
found = False
for i in range(10):
    for j in range(10):
        if i * j == 42:
            print(f"找到: {i} x {j}")
            found = True
            break
    if found:
        break

# 方式2: 提取为函数(推荐)
def find_pair():
    for i in range(10):
        for j in range(10):
            if i * j == 42:
                return i, j
    return None

result = find_pair()

# 方式3: 生成器 + next
def pairs():
    for i in range(10):
        for j in range(10):
            if i * j == 42:
                yield i, j

first = next(pairs(), None)   # 取第一个

while 嵌套

# while 嵌套同样适用
i = 1
while i <= 3:
    j = 1
    while j <= 3:
        print(i * j, end=" ")
        j += 1
    print()
    i += 1
# 1 2 3
# 2 4 6
# 3 6 9

嵌套性能注意

# 嵌套循环复杂度 O(n*m)
# 大输入时注意性能:
# 1. 能提前 break 就提前
# 2. 用集合/字典加速查找
# 3. 考虑是否真的需要两层遍历

# 查找加速示例
# ❌ O(n*m): 两两比较
for a in list_a:
    for b in list_b:
        if a == b: ...

# ✅ O(n+m): 用集合
set_b = set(list_b)
for a in list_a:
    if a in set_b: ...

实用案例

# 打印杨辉三角
rows = 5
triangle = [[1]]
for i in range(1, rows):
    row = [1]
    for j in range(1, i):
        row.append(triangle[i-1][j-1]
                   + triangle[i-1][j])
    row.append(1)
    triangle.append(row)

for row in triangle:
    print(row)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]

循环嵌套用于处理多维结构。核心:理解"外层一次、内层一轮"的执行顺序;需要提前退出全部时,优先用函数 return。

Python break 语句

Python break 语句

break 用于立即终止当前循环,跳出循环体,继续执行循环后的代码。

基本用法

for i in range(10):
    if i == 5:
        break
    print(i)
# 输出 0,1,2,3,4(到 5 停止)

# while 中同样适用
n = 0
while True:
    n += 1
    if n > 3:
        break
    print(n)     # 1,2,3

查找场景

# 找到目标立即停止
items = [3, 7, 1, 9, 4]
target = 9

for item in items:
    if item == target:
        print(f"找到了 {target}")
        break
else:
    print("未找到")    # break 时不执行

# 线性查找函数
def find_index(items, target):
    for i, item in enumerate(items):
        if item == target:
            return i
    return -1

idx = find_index(items, 9)   # 3

break 与 else 配合

# for-else: 循环"自然结束"(未 break)时执行 else
# 经典: 素数检测
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            break
    else:
        return True     # 无因子,是素数
    return False

print(is_prime(17))   # True
print(is_prime(18))   # False

嵌套循环中的 break

# break 只终止"最内层"当前循环
for i in range(3):
    for j in range(3):
        if j == 1:
            break          # 只退出内层
        print(i, j)        # 只输出 j=0 时
    print(f"--- 外层 {i} 继续 ---")

# 需要退出所有层:
# 1. 函数 return(推荐)
# 2. 标志位
# 3. 异常(不推荐)

用户输入退出

# 输入循环直到用户退出
while True:
    cmd = input("命令(q 退出): ")
    if cmd == "q":
        print("再见")
        break
    print(f"执行: {cmd}")

# 菜单示例
while True:
    print("\n1. 查询  2. 添加  3. 删除  0. 退出")
    choice = input("选择: ")
    if choice == "0":
        break
    elif choice == "1":
        print("查询功能")
    # ...

break 的常见误区

# 1. break 不能用于 if(只能用于循环)
# 错误: if x > 5: break(在循环外报错)

# 2. break 不退出函数(用 return)
def f():
    for i in range(5):
        if i == 2:
            break       # 只退出循环
    print("循环已退出")   # 会执行

# 3. 死循环中 break 是唯一的出口之一
# 确保 break 条件最终可达

break vs continue vs return

# break:    退出整个循环
# continue: 跳过本次迭代,继续下一次
# return:   退出整个函数(含循环)

for i in range(5):
    if i == 1:
        continue       # 跳过
    if i == 3:
        break          # 退出
    print(i)           # 0, 2

break 是循环的"紧急出口"。配合 else 判断"是否被中断",配合 return 提前返回,是高效查找与输入校验的关键。

Python continue 语句

Python continue 语句

continue 跳过当前循环迭代的剩余代码,直接进入下一次迭代。

基本用法

for i in range(5):
    if i == 2:
        continue      # 跳过 i=2
    print(i)
# 输出 0,1,3,4

# while 中同样适用
n = 0
while n < 5:
    n += 1
    if n == 3:
        continue
    print(n)      # 1,2,4,5

过滤场景

# 只处理满足条件的
for item in data:
    if item is None:
        continue        # 跳过空值
    if len(item) < 3:
        continue        # 跳过短值
    process(item)

# 奇偶分离
evens, odds = [], []
for x in range(10):
    if x % 2 == 0:
        evens.append(x)
        continue        # 进入下一次
    odds.append(x)

# 或更 Pythonic 的写法(不一定要 continue)
evens = [x for x in range(10) if x % 2 == 0]

嵌套循环中的 continue

# continue 只作用于所在的最内层循环
for i in range(3):
    for j in range(3):
        if j == 1:
            continue       # 只跳过内层 j=1
        print(i, j)        # 输出 j=0 和 j=2
    print("外层继续")

while 中使用注意

# 注意: continue 会跳过循环体剩余部分
# 包括更新条件的语句!容易死循环

# 错误示例(死循环!)
n = 0
while n < 5:
    if n == 2:
        continue      # n 不再增加!
    print(n)
    n += 1

# 正确: 更新语句放在 continue 之前
n = 0
while n < 5:
    n += 1           # 先更新
    if n == 2:
        continue
    print(n)         # 1,3,4,5

与推导式/过滤的对比

# continue 循环
result = []
for x in items:
    if x < 0:
        continue
    result.append(x * 2)

# 等价推导式(更简洁)
result = [x * 2 for x in items if x >= 0]

# 等价 filter
result = list(map(lambda x: x * 2,
                  filter(lambda x: x >= 0, items)))

# 选择: 简单过滤用推导式;复杂逻辑用 continue
# 需要副作用(打印/IO)时用循环

实用案例

# 处理用户输入: 跳过无效值
valid = []
while True:
    value = input("输入数字(回车结束): ")
    if not value:
        break
    if not value.replace("-", "").isdigit():
        print("无效, 跳过")
        continue       # 跳过非法输入
    valid.append(int(value))

print(f"有效数字: {valid}")

# 跳过文件中的空行和注释
for line in open("config.txt"):
    line = line.strip()
    if not line or line.startswith("#"):
        continue       # 跳过空行与注释
    process(line)

continue vs 条件嵌套

# 两种写法等价,选择更清晰的
# 写法1: continue(扁平化)
for x in items:
    if not valid(x):
        continue
    if not check(x):
        continue
    do(x)

# 写法2: 条件嵌套(缩进深)
for x in items:
    if valid(x):
        if check(x):
            do(x)

# continue 风格在复杂校验时更易读(扁平)

continue 用于"跳过不需要的迭代"。与 break(退出循环)配合,循环逻辑清晰可控。while 中记得先更新条件变量。

Python pass 语句

Python pass 语句

pass 是空操作语句:什么都不做,用于语法上需要语句但逻辑上不需要的场景。

基本用法

# 占位: 代码块不能为空
if x > 5:
    pass          # 暂时不写逻辑
else:
    print("小")

# 函数占位
def not_implemented():
    pass          # 先占位,后续实现

# 类占位
class MyModel:
    pass          # 结构先搭好

# 异常捕获后忽略
try:
    risky()
except ValueError:
    pass          # 暂时忽略该错误

为什么需要 pass

# Python 语法要求代码块不能为空!
# ❌ 语法错误
if x:
    # 空

# ✅ 用 pass 占位
if x:
    pass

# 其他语言用空花括号 {}
# Python 用 pass

占位设计(常用场景)

# 1. 接口/骨架设计
class BaseHandler:
    def handle(self, data):
        raise NotImplementedError  # 或 pass

# 2. TODO 占位
def process_order(order):
    # TODO: 实现订单处理
    pass

# 3. 分支骨架
def classify(x):
    if x < 0:
        pass    # TODO: 负数处理
    elif x == 0:
        return "零"
    else:
        pass    # TODO: 正数处理

pass vs return None

# pass: 不返回值(隐式 None),继续执行后面代码
def f1():
    pass
    print("后面还会执行")

# return: 立即返回
def f2():
    return
    print("不会执行")    # 不可达

# 函数无 return 时返回 None
result = f1()
print(result)   # None

pass 与 ...(Ellipsis)

# Python 中 ... 也可作为占位(简洁)
def placeholder():
    ...

# 等价于 pass,更紧凑
# 部分代码风格用 ... 表示"待实现"

# 但 pass 更常见、语义更明确

异常处理中的 pass

# 忽略异常(谨慎使用!)
try:
    result = int(input("数字: "))
except ValueError:
    pass          # 忽略错误输入

# 更好的做法: 给出默认值
try:
    result = int(input("数字: "))
except ValueError:
    result = 0

# 或至少记录
try:
    risky()
except Exception as e:
    pass
    # 或者 logging.warning(f"忽略: {e}")

最佳实践

# 1. 临时占位: 明确 TODO 标注
# 2. 忽略异常: 确保真的应该忽略(否则隐藏问题)
# 3. 空类/空函数骨架: 用 pass 保持结构
# 4. 长期"空实现"考虑 raise NotImplementedError
#    让调用方明确知道未实现

# 代码审查提示:
# 大量 pass 且无 TODO → 功能未完成,需确认

pass 是 Python 的"占位符":满足语法、标注待办。用对了是脚手架,用多了是欠债——记得补上实现。

Python Number(数字)

Python Number(数字)

数字是编程的基础。Python 支持整数、浮点数、复数,并提供丰富的数学函数。

数字类型

# int 整数(任意精度)
x = 42
y = -7
big = 10 ** 30      # 大整数无溢出

# float 浮点数
pi = 3.14159
e = 2.718
sci = 1.5e10        # 科学计数法

# complex 复数
c = 3 + 4j
c.real     # 3.0 实部
c.imag     # 4.0 虚部

# bool 是 int 的子类
True == 1     # True
False == 0    # True

类型转换

int("42")       # 字符串 → 整数
int(3.99)       # 浮点 → 整数(截断,不是四舍五入!)
int("0x1A", 16) # 十六进制 → 十进制 26
float("3.14")   # → 浮点
complex(1, 2)   # → 复数

# 进制
bin(10)    # '0b1010'
oct(10)    # '0o12'
hex(255)   # '0xff'
int("ff", 16)   # 255

常用运算

a, b = 10, 3
a + b / a - b / a * b
a // b      # 整除 3
a % b       # 取余 1
a ** b      # 幂 1000

# 内置数学函数
abs(-5)         # 5
round(3.14159, 2)  # 3.14(四舍五入)
round(2.5)      # 2(银行家舍入,注意!)
divmod(10, 3)   # (3, 1) 商和余
pow(2, 10)      # 1024
max(1, 5, 3) / min(1, 5, 3)
sum([1, 2, 3])

math 模块

import math

math.pi          # π
math.e           # e
math.sqrt(16)    # 4.0 平方根
math.pow(2, 10)  # 1024.0
math.floor(3.7)  # 3 向下取整
math.ceil(3.2)   # 4 向上取整
math.trunc(3.7)  # 3 截断
math.fabs(-5)    # 5.0
math.factorial(5)  # 120
math.gcd(12, 18)   # 6
math.log(100, 10)  # 2.0
math.log2(8)     # 3.0
math.exp(1)      # e
math.sin/cos/tan(x)
math.degrees(math.pi)  # 180.0
math.radians(180)      # π
math.inf        # 无穷
math.nan        # 非数字
math.isnan(math.nan)   # True
math.isfinite(1.0)     # True

random 模块

import random

random.random()         # [0,1) 浮点
random.randint(1, 10)   # [1,10] 整数
random.uniform(1, 5)    # [1,5) 浮点
random.choice(["a","b","c"])   # 随机选一个
random.choices(items, k=3)     # 选 k 个(可重复)
random.sample(items, 2)        # 不重复选 2 个
random.shuffle(items)          # 打乱(原地)
random.seed(42)                # 固定随机(可复现)

# 示例: 猜数字
secret = random.randint(1, 100)

浮点精度问题

# 二进制浮点不精确!
0.1 + 0.2      # 0.30000000000000004

# 解决:
# 1. 比较用容差
abs(0.1 + 0.2 - 0.3) < 1e-9     # True
# 2. 金额用 Decimal
from decimal import Decimal
Decimal("0.1") + Decimal("0.2")   # Decimal('0.3')
# 3. 分数用 Fraction
from fractions import Fraction
Fraction(1, 3) + Fraction(1, 6)   # 1/2

数字格式化

# f-string 格式化
price = 1234.5678
f"{price:.2f}"        # '1234.57' 两位小数
f"{price:,.2f}"       # '1,234.57' 千分位
f"{price:.0f}"        # '1235'
f"{price:010.2f}"     # '0001234.57' 补零
f"{price:.2e}"        # '1.23e+03' 科学计数

# 百分比
rate = 0.856
f"{rate:.1%}"         # '85.6%'

# 进制
f"{255:x}"            # 'ff'
f"{255:b}"            # '11111111'

性能与选择

# 大数计算: int 任意精度(不溢出)
# 金融计算: Decimal(精确)
# 科学计算: float + numpy
# 精确分数: Fraction

# 整数除法与取余:
# // 和 % 满足: a = (a//b)*b + a%b
# 注意负数: -7 // 3 = -3, -7 % 3 = 2
# (与 C 语言等行为不同,注意跨语言迁移)

数字处理是编程基础。掌握类型转换、math/random 模块与格式化,注意浮点精度陷阱,数值操作不再踩坑。

Python 字符串

Python 字符串

字符串是 Python 最常用的数据类型。本节系统介绍字符串的创建、操作、格式化与常用方法。

创建字符串

s1 = "双引号"
s2 = '单引号'
s3 = """三引号
支持多行
字符串"""
s4 = '''也可以用单三引号'''

# 转义
s = "换行\n 制表\t 引号\" 反斜杠\\"

# 原始字符串(不转义)
path = r"C:\Users\name"
regex = r"\d+"

# 字符串不可变(修改产生新字符串)

索引与切片

s = "Hello Python"
s[0]        # 'H'
s[-1]       # 'n' 负索引从末尾
s[0:5]      # 'Hello'
s[6:]       # 'Python'
s[:5]       # 'Hello'
s[::2]      # 'HloPto' 步长
s[::-1]     # 反转 'nohtyP olleH'

# 常用
len(s)      # 12
s[0] + s[-1]  # 'Hn'

字符串方法

s = "  Hello World  "

# 大小写
s.lower()      # '  hello world  '
s.upper()      # '  HELLO WORLD  '
s.title()      # '  Hello World  '
s.capitalize() # '  hello world  '
s.swapcase()

# 去除空白
s.strip()      # 'Hello World'
s.lstrip() / s.rstrip()

# 查找
s.find("World")    # 7(找不到 -1)
s.index("World")   # 7(找不到报错)
s.count("l")       # 3
s.startswith("  ") # True
s.endswith("d  ")  # True

# 判断
s.isalpha() / s.isdigit() / s.isalnum()
s.isspace() / s.isupper() / s.islower()

# 替换与分割
s.replace("World", "Python")
"a,b,c".split(",")        # ['a','b','c']
"a,b,c".split(",", 1)     # ['a','b,c'] 限制次数
"-".join(["a", "b", "c"]) # 'a-b-c'
"  a  b  ".split()        # ['a','b'] 自动处理空白

成员与比较

"World" in s        # True
"X" not in s        # True

# 比较: 字典序(按字符编码)
"abc" < "abd"       # True
"a" < "b"           # True
"10" < "9"          # True(字符串比较!注意)
# 数值比较要先转 int

字符串格式化

name, age = "Python", 30

# 1. f-string(推荐)
f"我是 {name}, {age} 岁"
f"{name!r}"        # repr 形式
f"{3.14159:.2f}"   # 3.14
f"{100:>5}"        # '  100' 右对齐
f"{100:<5}"        # '100  ' 左对齐
f"{100:^5}"        # ' 100 ' 居中

# 2. format 方法
"我是 {}, {} 岁".format(name, age)
"{1} 和 {0}".format("A", "B")
"{name} {age}".format(name=name, age=age)

# 3. 旧式 %(了解)
"我是 %s, %d 岁" % (name, age)

编码与字节

s = "中文"
s.encode("utf-8")        # b'\xe4...' 字节
s.encode("gbk")          # GBK 编码
b"bytes".decode("utf-8") # 字节 → 字符串

# 字符与编码
ord("A")       # 65
chr(65)        # 'A'
ord("中")      # 20013

# 长度注意
len("中文")     # 2(字符数)
len("中文".encode())   # 6(UTF-8 字节数)

多行与拼接

# 拼接
"a" + "b"       # 'ab'
"ab" * 3        # 'ababab'
a = "Hello"
b = "World"
full = a + ", " + b + "!"
f"{a}, {b}!"    # 更推荐

# 多行字符串
text = (
    "第一行 "
    "第二行 "
    "第三行"
)   # 括号内相邻字符串自动拼接

# join 拼接列表(高效)
", ".join(items)   # 而非循环 +=

字符串实用案例

# 反转
s[::-1]

# 单词计数
words = text.lower().split()
from collections import Counter
Counter(words).most_common(5)

# 验证密码强度
def password_ok(pwd):
    return (len(pwd) >= 8
            and any(c.isdigit() for c in pwd)
            and any(c.isalpha() for c in pwd))

# 清理文本
import re
clean = re.sub(r"[^\w\s]", "", text)  # 去标点

字符串操作是日常高频场景。掌握方法全家桶与 f-string 格式化,配合切片与编码处理,文本处理得心应手。

Python 列表(List)

Python 列表(List)

列表是 Python 最常用的容器:有序、可变、可存放任意类型。本节系统介绍列表操作。

创建列表

lst = [1, 2, 3]
mixed = [1, "a", 3.14, True]     # 任意混合
empty = []
nested = [[1, 2], [3, 4]]        # 嵌套
list("abc")                      # ['a','b','c']
list(range(5))                   # [0,1,2,3,4]
[0] * 5                          # [0,0,0,0,0]

# 推导式
[x * 2 for x in range(5)]        # [0,2,4,6,8]
[x for x in range(10) if x % 2 == 0]  # 偶数

索引与切片

lst = [10, 20, 30, 40, 50]
lst[0]      # 10
lst[-1]     # 50
lst[1:3]    # [20, 30]
lst[:2]     # [10, 20]
lst[::2]    # [10, 30, 50]
lst[::-1]   # 反转

# 切片修改
lst[1:3] = [99]    # [10, 99, 40, 50]
lst[1:3] = []      # 删除切片

增删改

lst = [1, 2]

# 增
lst.append(3)         # 末尾 [1,2,3]
lst.insert(0, 0)      # 指定位置 [0,1,2,3]
lst.extend([4, 5])    # 批量 [0,1,2,3,4,5]
lst += [6]            # 同 extend

# 删
lst.pop()             # 末尾弹 [0..5]
lst.pop(0)            # 指定索引弹
lst.remove(3)         # 删除第一个值3
del lst[0]            # 删除索引
lst.clear()           # 清空

# 改
lst[0] = "新值"       # 索引赋值

查找与统计

lst = [3, 1, 4, 1, 5, 9, 2]
lst.index(4)       # 2 首次出现位置
lst.count(1)       # 2 出现次数
3 in lst           # True
len(lst)           # 7
max(lst) / min(lst) / sum(lst)

# 排序
sorted(lst)             # 新列表排序(不改变原)
lst.sort()              # 原地排序
lst.sort(reverse=True)  # 降序
lst.sort(key=len)       # 按长度(自定义键)
sorted(lst, key=lambda x: x[1])  # 按第二元素

# 反转
lst.reverse() / lst[::-1]

遍历

for x in lst: print(x)
for i, x in enumerate(lst): print(i, x)
for a, b in zip(list1, list2): ...
for x in reversed(lst): ...
for x in sorted(lst): ...

# 遍历副本(边遍历边改)
for x in lst[:]:        # 副本
    if x < 0:
        lst.remove(x)   # 安全删除

复制与深浅拷贝

# 直接赋值是引用!
a = [1, 2, 3]
b = a              # 同一列表!
b.append(4)
print(a)           # [1,2,3,4] 受影响

# 浅拷贝
c = a.copy()       # 或 a[:] / list(a)
c.append(5)
print(a)           # 不受影响
# 但嵌套列表共享:
d = [[1], [2]]
e = d.copy()
e[0].append(9)
print(d)           # [[1,9],[2]] 受影响!

# 深拷贝
import copy
f = copy.deepcopy(d)   # 完全独立

列表推导式进阶

# 基本
[x ** 2 for x in range(5)]

# 带条件
[x for x in range(20) if x % 3 == 0]

# if-else 表达式
[x if x > 0 else 0 for x in nums]

# 嵌套
[(x, y) for x in range(3) for y in range(3)]

# 展平二维
flat = [item for row in matrix for item in row]

# 字符串处理
words = [w.strip() for w in text.split(",")]

# 性能: 推导式比 for+append 快,也更简洁

列表 vs 元组 vs 数组

# list: 可变,通用容器
# tuple: 不可变,更快更安全(常量、函数返回)
# array: 单一类型,省内存(较少用)
# numpy.ndarray: 数值计算(科学计算)

# 选择:
# 会修改 → list
# 不会修改/作字典键 → tuple
# 大量数值计算 → numpy

常用技巧

# 去重(保持顺序)
unique = list(dict.fromkeys(lst))

# 找最大/最小索引
max_idx = lst.index(max(lst))

# 分组
from collections import defaultdict
groups = defaultdict(list)
for item in items:
    groups[item["type"]].append(item)

# 滑动窗口
windows = [lst[i:i+3] for i in range(len(lst)-2)]

# 两个列表转字典
d = dict(zip(keys, values))

列表是 Python 的"主力容器"。掌握增删改查、切片、推导式与深浅拷贝,数据处理得心应手。

Python 元组

Python 元组

元组(Tuple)与列表类似,但不可变:创建后不能修改。用于表示"固定结构"的数据。

创建元组

t1 = (1, 2, 3)
t2 = 1, 2, 3          # 省略括号也可
single = (1,)         # 单元素必须加逗号!
empty = ()
tuple("abc")          # ('a','b','c')
tuple([1, 2])         # 列表 → 元组

# 注意:
(1)       # 1(不是元组!)
(1,)      # (1,)(是元组)

基本操作

t = (10, 20, 30, 40)

t[0]         # 10
t[-1]        # 40
t[1:3]       # (20, 30)
len(t)       # 4
20 in t      # True

# 不可变!
# t[0] = 99  → 报错 TypeError

# 拼接(生成新元组)
t + (50,)    # (10,20,30,40,50)
t * 2        # 重复

# 方法(少)
t.count(10)  # 1
t.index(20)  # 1

解包

point = (3, 4)
x, y = point          # 解包
print(x, y)           # 3 4

# 交换变量(经典)
a, b = b, a

# 多返回值
def min_max(nums):
    return min(nums), max(nums)
lo, hi = min_max([3, 1, 4])

# 扩展解包
first, *rest = (1, 2, 3, 4)
# first=1, rest=[2,3,4]
first, *middle, last = (1, 2, 3, 4, 5)
# first=1, middle=[2,3,4], last=5

元组 vs 列表

# 相同: 索引、切片、成员、遍历、拼接
# 不同:
# - 元组不可变(安全,防误改)
# - 元组可作字典键(可哈希)
# - 元组更快、更省内存
# - 列表有更多修改方法

# 选择指南:
# 坐标、常量、固定记录 → 元组
# 动态集合 → 列表

# 转换
list((1, 2))       # [1, 2]
tuple([1, 2])      # (1, 2)

元组作字典键

# 元组可哈希,可作字典键
locations = {
    (39.9, 116.4): "北京",
    (31.2, 121.5): "上海",
}
print(locations[(39.9, 116.4)])   # 北京

# 列表不可哈希,不能作键!
# {[1,2]: "x"} → 报错

命名元组(namedtuple)

from collections import namedtuple

# 带字段名的元组(可读性好)
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)

p.x          # 3(按名字访问)
p[0]         # 3(按索引也行)
x, y = p     # 解包

# 适用: 简单数据结构(替代类)
User = namedtuple("User", "name age email")
u = User("张三", 30, "z@e.com")
print(u.name, u.age)

# 有默认值
Point2 = namedtuple("Point2", "x y z", defaults=[0])
Point2(1, 2)      # z 默认为 0

常见场景

# 1. 函数多返回值
def get_user():
    return "张三", 30, "北京"   # 元组
name, age, city = get_user()

# 2. 记录固定结构数据
# 数据库行、坐标、RGB 颜色
colors = [(255, 0, 0), (0, 255, 0)]
for r, g, b in colors:
    print(r, g, b)

# 3. 安全集合(防误改)
DEFAULT_CONFIG = ("prod", 8080, True)
# 保证不会被意外修改

# 4. 字典遍历
for key, value in d.items():   # items 返回元组

陷阱与注意

# 1. 元组内可变元素仍可变!
t = ([1, 2], 3)
t[0].append(9)     # 元组本身没变,但元素变了
# t = ([1,2,9], 3)

# 2. 单元素元组记得逗号
# 3. 元组用于"固定结构",列表用于"动态集合"
# 4. 大元组拼接效率低(每次生成新对象)

元组是"不可变的列表":安全、可哈希、适合固定结构。配合解包与 namedtuple,数据表达简洁且语义清晰。

Python 字典(Dictionary)

Python 字典(Dictionary)

字典是键值对的集合:通过键快速查找值。是 Python 最重要的数据结构之一。

创建字典

d1 = {"name": "Python", "age": 30}
d2 = dict(name="Python", age=30)   # 关键字方式
d3 = dict([("a", 1), ("b", 2)])    # 键值对列表
d4 = {}                            # 空
d5 = dict(zip(keys, values))       # 两个列表合并

# 键的要求: 不可变类型(int/str/tuple)
# 值: 任意类型(可嵌套)

访问与修改

d = {"name": "Python", "age": 30}

# 访问
d["name"]        # 'Python'
d.get("name")    # 'Python'(安全)
d.get("x", "默认")  # '默认'(键不存在)
d.get("x")       # None

# 区别:
# d["x"] → KeyError(键不存在报错)
# d.get("x") → None(安全)

# 修改/新增
d["version"] = "3.11"    # 新增
d["age"] = 31            # 修改

# 删除
del d["age"]             # 删除键
d.pop("name")            # 删除并返回值
d.pop("x", None)         # 不存在返回默认
d.clear()                # 清空

# 判断
"name" in d              # True(查键)

遍历

d = {"a": 1, "b": 2, "c": 3}

for key in d:                # 键
for key in d.keys():         # 键(显式)
for value in d.values():     # 值
for key, value in d.items(): # 键值对(推荐)

# 保持插入顺序(Python 3.7+ 字典有序)

# 遍历时修改(先转列表)
for key in list(d.keys()):
    if d[key] < 2:
        del d[key]

字典方法

d = {"a": 1, "b": 2}

# 合并
d.update({"c": 3, "a": 10})   # 原地合并
merged = {**d, "d": 4}        # 新字典(展开)
# Python 3.9+: d | {"d": 4}

# 默认值
d.setdefault("e", 5)    # 键不存在则设置默认
d.setdefault("a", 99)   # 存在则不动(a 仍为 1)

# 获取所有键/值
list(d.keys()) / list(d.values()) / list(d.items())

# 复制
d.copy()               # 浅拷贝
import copy
copy.deepcopy(d)       # 深拷贝

defaultdict(默认值字典)

from collections import defaultdict

# 计数(经典用法)
counts = defaultdict(int)
for word in words:
    counts[word] += 1    # 自动初始化为 0

# 分组
groups = defaultdict(list)
for item in items:
    groups[item["type"]].append(item)

# 嵌套默认
dd = defaultdict(lambda: defaultdict(int))
dd["a"]["x"] = 1

# 普通 dict 需要先判断
# if key not in d: d[key] = []  → defaultdict 省事

Counter(计数器)

from collections import Counter

text = "hello world hello python"
c = Counter(text.split())
# Counter({'hello': 2, 'world': 1, 'python': 1})

c.most_common(1)     # [('hello', 2)] 最高频
c["hello"]           # 2
Counter("aabbb")     # Counter({'b': 3, 'a': 2})

# 合并
c1 = Counter("abc")
c2 = Counter("bcd")
c1 + c2     # Counter({'b': 2, 'a': 1, 'c': 1, 'd': 1})

OrderedDict 与排序

# 普通 dict 已保持插入顺序(3.7+)
# OrderedDict 提供额外方法(较少用)

# 按键/值排序
d = {"b": 2, "a": 3, "c": 1}
dict(sorted(d.items()))                 # 按键
dict(sorted(d.items(), key=lambda x: x[1]))  # 按值
dict(sorted(d.items(), key=lambda x: x[1],
            reverse=True))              # 降序

# top-k
from heapq import nlargest
nlargest(2, d.items(), key=lambda x: x[1])  # 最大2个

字典推导式

# 基本
{x: x ** 2 for x in range(5)}   # {0:0,1:1,2:4,3:9,4:16}

# 条件
{x: x for x in range(10) if x % 2 == 0}

# 转换
{word: len(word) for word in words}

# 交换键值
{v: k for k, v in d.items()}

嵌套字典

# 用户 → 订单 → 明细
data = {
    "user1": {
        "orders": [
            {"id": 1, "total": 99.5},
        ]
    }
}

data["user1"]["orders"][0]["total"]   # 99.5

# 安全访问嵌套
def safe_get(d, keys, default=None):
    for key in keys:
        if isinstance(d, dict) and key in d:
            d = d[key]
        else:
            return default
    return d

safe_get(data, ["user1", "orders", 0, "total"])

最佳实践

# 1. 访问用 get(避免 KeyError)
# 2. 计数用 defaultdict(int) / Counter
# 3. 分组用 defaultdict(list)
# 4. 嵌套访问封装安全函数
# 5. 遍历修改先转 list
# 6. 合并用 update 或 |

# 场景选择:
# 简单映射 → dict
# 计数 → Counter
# 默认值 → defaultdict
# 有序操作 → 普通 dict(已有序)/OrderedDict

字典是 Python 的"万能映射":快速查找、灵活嵌套。配合 collections 模块,数据统计与分组高效优雅。

Python 日期和时间

Python 日期和时间

Python 通过 datetime 模块处理日期时间:获取当前时间、格式化、计算差值、时区等。

获取当前时间

from datetime import datetime, date, time

now = datetime.now()        # 当前日期时间
today = date.today()        # 当前日期

# 访问字段
now.year / now.month / now.day
now.hour / now.minute / now.second
now.microsecond
now.weekday()    # 0=周一
now.isoweekday() # 1=周一

创建时间

# 指定时间
dt = datetime(2026, 8, 18, 10, 30, 0)

# 日期/时间单独
d = date(2026, 8, 18)
t = time(10, 30, 0)

# 从字符串解析
datetime.strptime("2026-08-18", "%Y-%m-%d")
datetime.fromisoformat("2026-08-18T10:30:00")

# 时间戳
datetime.now().timestamp()          # → 时间戳
datetime.fromtimestamp(1750000000)  # 时间戳 → 时间

格式化

dt = datetime(2026, 8, 18, 10, 30, 0)

dt.strftime("%Y-%m-%d")            # '2026-08-18'
dt.strftime("%Y/%m/%d %H:%M")      # '2026/08/18 10:30'
dt.strftime("%H:%M:%S")            # '10:30:00'
dt.strftime("%A")                  # 星期英文
dt.strftime("%Y 年 %m 月 %d 日")    # 中文格式

# 常用格式符
# %Y 年(4位) %m 月 %d 日
# %H 时(24) %I 时(12) %M 分 %S 秒
# %p AM/PM %A 星期全名 %a 星期缩写
# %j 年内第几天 %U 年内第几周

# f-string 也支持
f"{dt:%Y-%m-%d %H:%M}"

日期运算

from datetime import timedelta

now = datetime.now()
now + timedelta(days=1)         # 明天
now - timedelta(days=7)         # 一周前
now + timedelta(hours=2)        # 两小时后
now + timedelta(minutes=30)
now + timedelta(weeks=1)

# 差值
d1 = datetime(2026, 8, 1)
d2 = datetime(2026, 8, 18)
diff = d2 - d1       # timedelta(days=17)
diff.days            # 17
diff.total_seconds() # 1468800.0

# timedelta 常用字段
td = timedelta(days=1, hours=2, minutes=30)
td.total_seconds()   # 95400.0

日期比较

d1 < d2 / d1 == d2 / d1 > d2     # 直接比较

# 判断区间
start = datetime(2026, 8, 1)
end = datetime(2026, 8, 31)
target = datetime(2026, 8, 18)
start <= target <= end    # True

time 模块(底层)

import time

# 时间戳
time.time()          # 当前时间戳
time.sleep(1)        # 暂停 1 秒

# 性能计时
start = time.time()
do_work()
elapsed = time.time() - start

# 更精确: perf_counter(不受系统时间影响)
start = time.perf_counter()
do_work()
elapsed = time.perf_counter() - start

# 结构化时间
time.localtime()     # 本地时间元组
time.gmtime()        # UTC 时间

时区处理

from datetime import timezone, timedelta

# UTC 时间
utc_now = datetime.now(timezone.utc)

# 指定时区
cst = timezone(timedelta(hours=8))    # 东八区
now_cst = datetime.now(cst)

# 转换
utc_now.astimezone(cst)

# 存储建议: 统一 UTC,展示转本地
# 数据库存 UTC,前端展示时转时区

calendar 模块

import calendar

calendar.month(2026, 8)      # 打印月历
calendar.isleap(2024)        # True 闰年
calendar.weekday(2026, 8, 18)  # 1(周二)

# 某月天数
import calendar
calendar.monthrange(2026, 8)   # (5, 31) 首日周几,天数

实用案例

# 1. 计算年龄
def calc_age(birth):
    today = date.today()
    age = today.year - birth.year
    if (today.month, today.day) < (birth.month, birth.day):
        age -= 1
    return age

# 2. 生成日期序列
dates = [start + timedelta(days=i)
         for i in range((end - start).days + 1)]

# 3. 日志时间戳
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"backup_{timestamp}.zip"

# 4. 超时判断
deadline = start + timedelta(seconds=10)
if datetime.now() > deadline:
    print("超时")

最佳实践

# 1. 存储用 UTC,展示转本地时区
# 2. 比较统一用 datetime 对象(勿混 str)
# 3. 解析外部日期用 strptime 并指定格式
# 4. 计时用 perf_counter,不用 time.time
# 5. 计算差值用 timedelta,勿手算秒数
# 6. 复杂时区用第三方库 pytz/zoneinfo

# 注意: strptime 解析失败会抛 ValueError
try:
    dt = datetime.strptime(s, "%Y-%m-%d")
except ValueError:
    print("日期格式错误")

日期时间是程序的"时钟"。掌握 datetime + timedelta + strftime 三件套,配合时区规范,时间处理不再头疼。

Python 函数

Python 函数

函数是组织代码的基本单元:封装逻辑、避免重复、便于测试。本节系统介绍 Python 函数。

定义与调用

def greet(name):
    """问候函数(文档字符串)"""
    return f"你好, {name}!"

# 调用
print(greet("Python"))

# 无返回值(返回 None)
def log(msg):
    print(f"[LOG] {msg}")

result = log("hi")    # None

# 函数是第一类对象
f = greet            # 赋值
f("X")               # 调用
funcs = [greet, log] # 放容器

参数类型

# 1. 位置参数
def f(a, b, c): ...

# 2. 默认参数(必须放最后)
def f(a, b=10, c="x"): ...
f(1)          # b=10, c="x"
f(1, 2)       # b=2
# 注意: 默认参数用不可变对象!
# def f(lst=[]): → 陷阱!用 None

# 3. 关键字参数
def f(a, b, c): ...
f(b=2, a=1, c=3)     # 顺序随意

# 4. 位置 + 关键字混合
# 位置参数在前,关键字在后
f(1, b=2, c=3)

可变参数

# *args: 任意多个位置参数 → 元组
def sum_all(*args):
    return sum(args)
sum_all(1, 2, 3)      # 6

# **kwargs: 任意多个关键字参数 → 字典
def show(**kwargs):
    for k, v in kwargs.items():
        print(f"{k}={v}")
show(name="Py", ver=3)

# 组合(完整形式)
def func(a, b=10, *args, c=20, **kwargs):
    print(a, b, args, c, kwargs)

# 强制关键字参数(* 后)
def f(a, *, b):
    return a + b
f(1, b=2)     # OK
# f(1, 2)     # 报错!b 必须关键字

解包传参

# 列表/元组解包
def add(a, b, c):
    return a + b + c

nums = [1, 2, 3]
add(*nums)          # 6

# 字典解包
d = {"a": 1, "b": 2, "c": 3}
add(**d)            # 6

# 应用: 动态调用
config = {"host": "localhost", "port": 8080}
connect(**config)

返回值

# 多返回值(元组)
def stats(nums):
    return min(nums), max(nums), sum(nums)
lo, hi, total = stats([1, 5, 3])

# 条件返回
def classify(x):
    if x > 0: return "正"
    if x < 0: return "负"
    return "零"

# 提前返回(守卫子句)
def process(data):
    if not data:
        return None
    if not valid(data):
        return "invalid"
    return result

作用域

x = 10        # 全局

def f():
    y = 20     # 局部
    print(x)   # 可读全局
    # x = 30   # 会创建局部!需 global 声明

def g():
    global x   # 声明使用全局
    x = 99

# 规则: LEGB
# Local(局部) → Enclosing(外层函数)
# → Global(全局) → Built-in(内建)

# 闭包
def counter():
    count = 0
    def inc():
        nonlocal count   # 修改外层变量
        count += 1
        return count
    return inc

c = counter()
c()  # 1
c()  # 2

lambda 匿名函数

# 单行表达式函数
square = lambda x: x ** 2
square(5)         # 25

# 与排序/映射配合
pairs = [(1, "b"), (2, "a")]
sorted(pairs, key=lambda p: p[1])

items = [1, 2, 3]
list(map(lambda x: x * 2, items))      # [2,4,6]
list(filter(lambda x: x % 2 == 0, items))  # [2]

# 优先用推导式(更清晰)
[x * 2 for x in items]
[x for x in items if x % 2 == 0]

# lambda 只适合简单表达式,复杂逻辑用 def

装饰器

# 函数增强: 在不动原函数的情况下加功能
def timer(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时 "
              f"{time.perf_counter()-start:.4f}s")
        return result
    return wrapper

@timer          # 等价 slow_func = timer(slow_func)
def slow_func():
    time.sleep(0.1)

slow_func()     # 自动计时

# 带参数的装饰器
def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def say():
    print("hi")

函数式工具

# map / filter / reduce
from functools import reduce

nums = [1, 2, 3, 4, 5]
list(map(str, nums))          # ['1',...]
list(filter(lambda x: x > 2, nums))  # [3,4,5]
reduce(lambda a, b: a + b, nums)     # 15

# 优先推导式(更 Pythonic)
[str(n) for n in nums]
[n for n in nums if n > 2]

# functools 其他
from functools import partial, lru_cache

# 偏函数(固定参数)
add = lambda a, b: a + b
add5 = partial(add, 5)
add5(3)          # 8

# 缓存(性能优化)
@lru_cache(maxsize=128)
def fib(n):
    if n < 2: return n
    return fib(n-1) + fib(n-2)
fib(100)         # 秒出

最佳实践

# 1. 函数单一职责: 一个函数做一件事
# 2. 用文档字符串描述功能
# 3. 参数命名清晰,少用魔法数字
# 4. 默认参数用 None 而非可变对象
# 5. 尽早 return(守卫子句)
# 6. 变量作用域最小化
# 7. 复杂逻辑拆分成小函数

# 示例: 好的函数
def calculate_total(prices, tax_rate=0.1):
    """计算含税总价。
    prices: 价格列表
    tax_rate: 税率(默认 0.1)
    """
    if not prices:
        return 0.0
    subtotal = sum(prices)
    return subtotal * (1 + tax_rate)

函数是代码复用的基石。掌握参数类型、可变参数、作用域与装饰器,配合"单一职责"与"守卫子句",代码质量显著提升。

Python 模块

Python 模块

模块是 Python 组织代码的方式:一个 .py 文件就是一个模块,包是模块的集合。模块化让代码可复用、可维护。

导入模块

# 方式1: 导入整个模块
import math
math.sqrt(16)          # 4.0

# 方式2: 导入部分
from math import sqrt, pi
sqrt(16)               # 直接用

# 方式3: 别名
import numpy as np
import pandas as pd

# 方式4: 通配符(不推荐,污染命名空间)
from math import *

创建自己的模块

# mymodule.py
"""我的模块"""
VERSION = "1.0"

def greet(name):
    return f"Hello, {name}"

class Calculator:
    def add(self, a, b):
        return a + b

# 使用
# main.py
import mymodule
print(mymodule.VERSION)
print(mymodule.greet("World"))
calc = mymodule.Calculator()

__name__ 与主模块

# 每个模块都有 __name__
# - 直接运行时: __name__ == "__main__"
# - 被导入时: __name__ == 模块名

# mymodule.py
def main():
    print("程序入口")

if __name__ == "__main__":
    main()       # 直接运行时执行
# 被导入时不执行 main(避免副作用)

包(Package)

# 目录结构
mypackage/
├── __init__.py      # 包标记(可为空)
├── module_a.py
└── sub/
    └── module_b.py

# 导入
import mypackage.module_a
from mypackage import module_a
from mypackage.sub import module_b

# __init__.py 可定义包级内容
# __all__ = ["module_a"]  # 控制 * 导入范围

常用标准库

import os                # 操作系统
import sys               # 系统参数
import json              # JSON
import re                # 正则
import math / random     # 数学/随机
import datetime          # 日期时间
import collections       # 容器工具
import itertools         # 迭代工具
import functools         # 函数工具
import pathlib           # 路径操作
import subprocess        # 子进程
import threading         # 多线程
import logging           # 日志
import unittest          # 测试
import urllib            # 网络请求

# 常用: os/sys
os.getcwd()          # 当前目录
os.listdir(".")      # 列出文件
os.path.join("a", "b")   # 路径拼接
sys.argv             # 命令行参数
sys.path             # 模块搜索路径

第三方包

# 安装
pip install requests pandas

# 常用第三方:
# Web: requests / flask / django
# 数据: numpy / pandas / matplotlib
# AI:   torch / scikit-learn
# 工具: tqdm(进度条) / rich(美化输出)

# 管理依赖
pip freeze > requirements.txt    # 导出
pip install -r requirements.txt  # 安装

模块搜索路径

# 导入时按 sys.path 顺序查找
import sys
print(sys.path)
# ['', '/usr/lib/python3.11', ...]

# 当前目录优先 → 标准库 → 第三方

# 添加路径
sys.path.append("/my/libs")
# 或环境变量 PYTHONPATH
# 或 site-packages

# 命名冲突注意: 自定义模块勿与标准库同名

reload 与重新导入

# 交互式开发中修改模块后重载
import importlib
import mymodule
importlib.reload(mymodule)

# 或重启解释器(更可靠)

模块最佳实践

# 1. 每个模块职责单一(一个 .py 一个主题)
# 2. 顶层只写常量/函数/类,副作用放 main
# 3. 用 __all__ 明确公共接口
# 4. 相对导入: from . import sibling
#    (包内模块用相对导入)
# 5. 命名: 小写下划线 my_module.py
# 6. 避免循环导入

# 组织建议
# 小项目: 单文件即可
# 中项目: 按功能分包
# 大项目: src 布局 + 包管理工具

模块化让 Python 代码"积木化":标准库开箱即用、第三方包丰富生态、自定义模块复用逻辑。合理组织,项目可维护性大增。

Python 文件I/O

Python 文件I/O

文件读写是程序与外部数据交互的基础。Python 提供简洁的文件操作接口,推荐使用 with 语句自动管理资源。

打开文件

# 语法: open(path, mode, encoding)
f = open("data.txt", "r", encoding="utf-8")
# 读取操作...
f.close()          # 记得关闭!

# 模式:
# "r"  只读(默认)
# "w"  写入(覆盖,不存在则创建)
# "a"  追加
# "x"  创建(已存在报错)
# "b"  二进制(如 "rb" "wb")
# "+"  读写("r+" "w+")

# 推荐: with 自动关闭
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
# 退出 with 自动 close,无需手动

读取文件

# 全部读取
with open("data.txt", encoding="utf-8") as f:
    content = f.read()          # 字符串

# 逐行读取(大文件推荐)
with open("data.txt", encoding="utf-8") as f:
    for line in f:              # 迭代器,省内存
        print(line.rstrip())

# 读取所有行(列表)
with open("data.txt", encoding="utf-8") as f:
    lines = f.readlines()       # ['line1\n', ...]

# 一次读一行
with open("data.txt", encoding="utf-8") as f:
    line1 = f.readline()
    line2 = f.readline()

# 便捷函数
content = open("data.txt", encoding="utf-8").read()
# 但不推荐(不关闭),了解即可

写入文件

# 覆盖写入
with open("out.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
    f.write("第二行\n")

# 追加
with open("out.txt", "a", encoding="utf-8") as f:
    f.write("追加行\n")

# 写多行
lines = ["a", "b", "c"]
with open("out.txt", "w", encoding="utf-8") as f:
    f.writelines(line + "\n" for line in lines)

# print 到文件
with open("out.txt", "w", encoding="utf-8") as f:
    print("hello", file=f)

二进制文件

# 读取二进制(图片等)
with open("img.png", "rb") as f:
    data = f.read()          # bytes

# 写入二进制
with open("copy.png", "wb") as f:
    f.write(data)

# 复制文件
with open("src.png", "rb") as src, \
     open("dst.png", "wb") as dst:
    dst.write(src.read())

文件路径操作

import os
from pathlib import Path

# os 方式
os.path.exists("data.txt")     # 是否存在
os.path.isfile("data.txt")     # 是否文件
os.path.isdir("dir")           # 是否目录
os.path.getsize("data.txt")    # 大小
os.path.join("dir", "sub", "f.txt")  # 拼接路径
os.path.basename("/a/b.txt")   # 'b.txt'
os.path.dirname("/a/b.txt")    # '/a'
os.path.splitext("a.txt")      # ('a', '.txt')

# pathlib(现代推荐)
p = Path("dir/sub/data.txt")
p.exists() / p.is_file() / p.is_dir()
p.name          # 'data.txt'
p.stem          # 'data'
p.suffix        # '.txt'
p.parent        # 'dir/sub'
p / "other.txt" # 拼接
Path("dir").mkdir(parents=True, exist_ok=True)
Path("data.txt").read_text(encoding="utf-8")
Path("data.txt").write_text("内容", encoding="utf-8")

目录操作

import os
import shutil

# 列出
os.listdir(".")          # 当前目录
for name in os.listdir("."):
    if name.endswith(".py"):
        print(name)

# glob 模式匹配
import glob
glob.glob("*.py")            # 当前目录 py
glob.glob("**/*.py", recursive=True)  # 递归

# 创建/删除
os.makedirs("a/b/c", exist_ok=True)   # 递归创建
os.rmdir("a")              # 删除空目录
shutil.rmtree("a")         # 递归删除(慎用!)

# 移动/复制/重命名
shutil.copy("a.txt", "b.txt")    # 复制文件
shutil.move("a.txt", "dir/a.txt")  # 移动
os.rename("a.txt", "c.txt")      # 重命名

# 删除文件
os.remove("c.txt")

文件编码

# 读写时指定编码(处理中文)
with open("data.txt", "r", encoding="utf-8") as f:
    ...

# 常见问题:
# UnicodeDecodeError: 编码不匹配
# 解决: 确认文件真实编码
# 尝试 gbk / utf-8-sig(带 BOM)

# 读取未知编码文件(尝试)
for enc in ["utf-8", "gbk", "utf-8-sig"]:
    try:
        with open("f.txt", encoding=enc) as f:
            text = f.read()
        break
    except UnicodeDecodeError:
        continue

异常处理

# 文件不存在等错误
try:
    with open("missing.txt", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print("文件不存在")
except PermissionError:
    print("无权限")
except UnicodeDecodeError:
    print("编码错误")

# 常见异常:
# FileNotFoundError / PermissionError
# IsADirectoryError / UnicodeDecodeError

实用案例

# 1. 统计文本词频
from collections import Counter
with open("text.txt", encoding="utf-8") as f:
    words = f.read().lower().split()
top = Counter(words).most_common(5)

# 2. 逐行处理大文件
with open("big.log", encoding="utf-8") as f:
    for line in f:
        if "ERROR" in line:
            print(line.rstrip())

# 3. 合并多个文件
with open("merged.txt", "w", encoding="utf-8") as out:
    for name in ["a.txt", "b.txt"]:
        with open(name, encoding="utf-8") as f:
            out.write(f.read())

# 4. 读取 CSV(简单方式)
with open("data.csv", encoding="utf-8") as f:
    for line in f:
        row = line.strip().split(",")
        print(row)

最佳实践

# 1. 永远用 with 打开文件(自动关闭)
# 2. 指定 encoding="utf-8"(跨平台一致)
# 3. 大文件逐行处理,勿整体 read
# 4. 路径操作用 pathlib(更现代)
# 5. 处理可能出现的异常
# 6. 写文件前确保目录存在(mkdir)

# 工具: tempfile 临时文件
import tempfile
with tempfile.NamedTemporaryFile(
        suffix=".txt", delete=True) as tmp:
    tmp.write(b"temp data")
    print(tmp.name)   # /tmp/xxx.txt

文件 I/O 是程序的数据出入口。掌握 with 语句、读写模式、编码处理与 pathlib,文件操作安全高效。

Python 异常处理

Python 异常处理

异常是程序运行时的错误。异常处理让程序在出错时优雅降级,而非崩溃。本节系统介绍 try/except/else/finally 与异常体系。

基本结构

try:
    result = 10 / 0
except ZeroDivisionError:
    print("除数不能为零")

# 捕获异常对象
try:
    num = int("abc")
except ValueError as e:
    print(f"转换失败: {e}")

# 捕获多种异常
try:
    risky()
except (ValueError, TypeError) as e:
    print(f"类型错误: {e}")

完整结构

try:
    # 可能出错的代码
    data = process()
except ValueError:
    print("值错误")
except Exception as e:      # 兜底
    print(f"未知错误: {e}")
else:
    print(f"无异常,结果: {data}")   # 无异常时执行
finally:
    print("无论如何都执行")          # 清理资源

# else: try 无异常时执行
# finally: 无论是否异常都执行(关闭资源)

常见异常类型

# 异常层级(部分):
# BaseException
#  ├── KeyboardInterrupt  (Ctrl+C)
#  ├── SystemExit
#  └── Exception
#       ├── ArithmeticError
#       │    ├── ZeroDivisionError
#       │    └── OverflowError
#       ├── LookupError
#       │    ├── IndexError       索引越界
#       │    └── KeyError         字典键不存在
#       ├── ValueError            值错误
#       ├── TypeError             类型错误
#       ├── FileNotFoundError     文件不存在
#       ├── PermissionError       权限错误
#       └── ...(大量具体异常)

# 只捕获 Exception 及其子类
# 不捕获 KeyboardInterrupt/SystemExit

抛出异常

# raise 主动抛出
def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

# 指定类型
raise TypeError("类型不匹配")
raise Exception("通用错误")

# 从异常中抛出异常(链式)
try:
    divide(1, 0)
except ValueError as e:
    raise RuntimeError("计算失败") from e
# 保留原始异常(排查根因)

# assert(断言,开发期检查)
def set_age(age):
    assert 0 <= age <= 150, "年龄不合法"
    return age
# 断言失败抛 AssertionError
# 生产环境可禁用(python -O)

自定义异常

# 定义业务异常
class AppError(Exception):
    """应用基础异常"""
    pass

class ValidationError(AppError):
    """数据校验失败"""
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"{field}: {message}")

class NotFoundError(AppError):
    """资源不存在"""
    pass

# 使用
def get_user(user_id):
    if user_id < 0:
        raise ValidationError("user_id", "不能为负")
    if user_id == 0:
        raise NotFoundError("用户不存在")
    return {"id": user_id}

try:
    get_user(0)
except ValidationError as e:
    print(f"校验失败: {e.field} - {e.message}")
except NotFoundError:
    print("未找到")
except AppError:
    print("其他业务错误")

# 好处: 调用方可精确捕获业务错误

异常链与上下文

# __context__: 异常被处理时自动记录
# __cause__: from 指定原因
# traceback: 完整堆栈

import traceback
try:
    divide(1, 0)
except Exception:
    traceback.print_exc()   # 打印完整堆栈

# 记录异常(日志)
import logging
logging.basicConfig(level=logging.ERROR)
try:
    risky()
except Exception as e:
    logging.exception("操作失败")   # 含堆栈

with 与上下文管理

# with 语句处理资源(文件、锁、连接)
with open("f.txt") as f:      # 自动关闭
    data = f.read()

# 自定义上下文管理器
class ManagedFile:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print("打开资源")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("释放资源")
        return False      # False: 异常继续抛出

with ManagedFile("f.txt") as f:
    print("使用中")
# 输出: 打开资源 / 使用中 / 释放资源

# 更简单: contextlib
from contextlib import contextmanager

@contextmanager
def managed():
    print("进入")
    try:
        yield
    finally:
        print("退出")

with managed():
    print("使用")

异常处理最佳实践

# 1. 捕获具体异常,避免裸 except:
# ❌ except: / except Exception: 吞掉所有
# ✅ except ValueError: 精确处理

# 2. 不要用异常控制正常流程
# ❌
try:
    value = d["key"]
except KeyError:
    value = default
# ✅
value = d.get("key", default)

# 3. 该抛出就抛,别吞
# 捕获后什么都不做 = 隐藏 bug

# 4. 资源用 with 管理
# 5. 关键错误记录日志(含堆栈)
# 6. 自定义异常继承自 Exception(或业务基类)

# 分层处理:
# - 底层: 让异常向上传播
# - 边界(API/UI): 捕获并转换
# - 顶层: 兜底处理,避免崩溃

实用模式

# 1. 重试模式
import time
for attempt in range(3):
    try:
        result = api_call()
        break
    except ConnectionError:
        if attempt == 2:
            raise
        time.sleep(2 ** attempt)   # 退避

# 2. 默认值模式
try:
    value = int(text)
except (ValueError, TypeError):
    value = 0

# 3. 部分成功模式
errors = []
for item in items:
    try:
        process(item)
    except Exception as e:
        errors.append((item, e))
# 汇总 errors 报告

# 4. 抑制已知异常(contextlib)
from contextlib import suppress
with suppress(FileNotFoundError):
    os.remove("maybe_missing.txt")

异常处理是程序的"安全气囊":精确捕获、优雅降级、记录日志、释放资源。处理好异常,程序才健壮可用。

Python 面向对象

Python 面向对象

面向对象编程(OOP)用"类与对象"组织代码:封装数据与行为、复用逻辑。Python 支持完整的 OOP 特性。

类与对象

class Dog:
    """狗类"""
    species = "犬科"          # 类属性(所有实例共享)

    def __init__(self, name, age):
        self.name = name      # 实例属性
        self.age = age

    def bark(self):
        return f"{self.name}: 汪汪!"

    def info(self):
        return f"{self.name}, {self.age} 岁"

# 创建对象
d1 = Dog("旺财", 3)
d2 = Dog("小白", 2)

d1.bark()      # '旺财: 汪汪!'
d1.info()      # '旺财, 3 岁'
Dog.species    # '犬科'(类属性)

self 与 __init__

# self: 实例自身的引用(必须为第一个参数)
# __init__: 构造方法(创建对象时初始化)

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def distance(self, other):
        return ((self.x - other.x) ** 2
                + (self.y - other.y) ** 2) ** 0.5

p1 = Point(0, 0)
p2 = Point(3, 4)
p1.distance(p2)      # 5.0

# 方法只是"绑定到实例的函数"
Point.distance(p1, p2)   # 等价调用

属性与封装

# 私有约定: 下划线前缀(约定,非强制)
class Account:
    def __init__(self, balance=0):
        self._balance = balance    # 约定私有
        self.__secret = "隐藏"      # 名字重整(更私有)

    def deposit(self, n):
        if n > 0:
            self._balance += n
        return self._balance

    def get_balance(self):
        return self._balance

# 属性 property(推荐)
class Account:
    def __init__(self, balance=0):
        self._balance = balance

    @property
    def balance(self):           # 读取
        return self._balance

    @balance.setter
    def balance(self, value):    # 赋值(校验)
        if value < 0:
            raise ValueError("余额不能为负")
        self._balance = value

acc = Account(100)
acc.balance          # 100(像属性一样读)
acc.balance = 200    # 走 setter(校验)

继承

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "..."

    def info(self):
        return f"动物: {self.name}"

class Dog(Animal):
    def speak(self):            # 重写
        return "汪汪"

class Cat(Animal):
    def speak(self):
        return "喵喵"

    def info(self):
        return f"猫: {super().info()}"  # 调用父类

# 多态
animals = [Dog("旺财"), Cat("咪咪")]
for a in animals:
    print(a.speak())    # 汪汪 / 喵喵

# 检查类型
isinstance(d, Dog)      # True
issubclass(Dog, Animal) # True

多继承与 MRO

class A:
    def method(self): return "A"

class B:
    def method(self): return "B"

class C(A, B):      # 多继承
    pass

c = C()
c.method()          # 'A'(按 MRO 顺序)

# MRO: 方法解析顺序
C.__mro__           # (C, A, B, object)

# 多继承慎用!复杂层级易混淆
# 优先组合而非继承

# super() 在多继承中的协作
class D(A, B):
    def method(self):
        return super().method() + " + D"

魔术方法

class Vector:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):          # 开发者表示
        return f"Vector({self.x}, {self.y})"

    def __str__(self):           # 用户表示(str())
        return f"({self.x}, {self.y})"

    def __add__(self, other):    # +
        return Vector(self.x + other.x,
                      self.y + other.y)

    def __eq__(self, other):     # ==
        return (self.x, self.y) == (other.x, other.y)

    def __len__(self):           # len()
        return int(abs(complex(self.x, self.y)))

v1 = Vector(1, 2)
v2 = Vector(3, 4)
v1 + v2          # Vector(4, 6)
v1 == Vector(1, 2)  # True
str(v1)          # '(1, 2)'

# 常用魔术方法:
# __init__/__repr__/__str__
# __add__/__sub__/__mul__/__eq__/__lt__
# __len__/__getitem__/__setitem__
# __iter__/__next__
# __call__: 实例可调用
# __enter__/__exit__: with 支持
# __getattr__/__setattr__

类方法与静态方法

class Student:
    count = 0

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

    @classmethod
    def total(cls):            # 类方法: 操作类
        return f"学生总数: {cls.count}"

    @staticmethod
    def validate(name):        # 静态方法: 工具函数
        return len(name) > 0

    @classmethod
    def create(cls, name):     # 工厂方法
        if cls.validate(name):
            return cls(name)
        return None

s1 = Student("张三")
Student.total()      # '学生总数: 1'
Student.validate("") # False

dataclass(数据类)

from dataclasses import dataclass, field

# 自动生成 __init__/__repr__/__eq__ 等
@dataclass
class Product:
    name: str
    price: float
    stock: int = 0                # 默认值
    tags: list = field(default_factory=list)  # 可变默认!

p1 = Product("键盘", 99.5, 10)
p2 = Product("键盘", 99.5, 10)
print(p1)            # Product(name='键盘', price=99.5, stock=10)
p1 == p2             # True(自动实现)

# 对比普通类: 少写大量样板代码
# 适合数据载体(配置、DTO、记录)

OOP 最佳实践

# 1. 组合优于继承(has-a 优于 is-a)
# 2. 单一职责: 一个类做一件事
# 3. 封装: 属性用 property 控制访问
# 4. 少用多继承,保持层级浅
# 5. 数据类用 dataclass
# 6. 魔术方法让类融入 Python 语法
# 7. 不要过度设计(简单场景用函数即可)

# 组合示例
class Engine:
    def start(self): ...

class Car:
    def __init__(self):
        self.engine = Engine()   # 组合
    def start(self):
        self.engine.start()

Python OOP 灵活而优雅:类/继承/多态/魔术方法/dataclass 一应俱全。按需使用,保持简单,是最高原则。

Python 正则表达式

Python 正则表达式

正则表达式(Regex)用于文本的匹配、查找、替换与提取。Python 通过 re 模块提供支持。

基本用法

import re

# match: 从开头匹配
re.match(r"\d+", "123abc")      # 匹配对象
re.match(r"abc", "123abc")       # None(开头不匹配)

# search: 任意位置匹配
re.search(r"\d+", "abc123def")  # 匹配 '123'

# findall: 找全部
re.findall(r"\d+", "a1b22c333") # ['1', '22', '333']

# sub: 替换
re.sub(r"\d+", "#", "a1b22c")   # 'a#b#c'

# split: 分割
re.split(r"[,\s]+", "a, b  c")  # ['a','b','c']

# 匹配对象
m = re.search(r"(\d{4})-(\d{2})", "2026-08")
m.group()       # '2026-08' 整个匹配
m.group(1)      # '2026'
m.group(2)      # '08'
m.span()        # (0, 7) 位置
m.start() / m.end()

元字符与语法

# 字符类
.         # 任意字符(除换行)
\d        # 数字 [0-9]
\D        # 非数字
\w        # 单词字符 [a-zA-Z0-9_]
\W        # 非单词
\s        # 空白(空格/制表/换行)
\S        # 非空白

# 量词
*         # 0次或多次
+         # 1次或多次
?         # 0次或1次
{n}       # 恰好 n 次
{n,}      # 至少 n 次
{n,m}     # n 到 m 次

# 锚点
^         # 开头
$         # 结尾
\b        # 单词边界

# 分组与或
(abc)     # 分组
a|b       # 或
[abc]     # 字符集: a/b/c 之一
[a-z]     # 范围
[^0-9]    # 非数字

# 转义: 特殊字符需 \ 转义
# \. \* \+ \? \[ \] \( \) \|

常用模式示例

# 邮箱(简化)
re.fullmatch(r"[\w.+-]+@[\w-]+\.[\w.]+",
             "user@example.com")

# 手机号(中国,简化)
re.fullmatch(r"1[3-9]\d{9}", "13812345678")

# 身份证(18位)
re.fullmatch(r"\d{17}[\dX]", "110101199001011234")

# URL
re.fullmatch(r"https?://[\w.-]+(?:/[\w./?&=%-]*)?",
             "https://example.com/path?a=1")

# IP 地址(简化)
re.fullmatch(r"\d{1,3}(\.\d{1,3}){3}", "192.168.1.1")

# 日期
re.fullmatch(r"\d{4}-\d{2}-\d{2}", "2026-08-18")

# 中文字符
re.findall(r"[\u4e00-\u9fff]+", "Hello 世界!")  # ['世界']

贪婪与懒惰

text = "onetwo"

# 贪婪: 尽可能多匹配
re.findall(r"<.+>", text)
# ['onetwo'] 整个

# 懒惰: 尽可能少匹配(加 ?)
re.findall(r"<.+?>", text)
# ['', '', '', '']

# 需要分组精确提取
re.findall(r"(.*?)", text)   # ['one']

编译正则(性能)

# 重复使用同一正则时,先编译
phone_re = re.compile(r"1[3-9]\d{9}")

phone_re.findall(text)
phone_re.search(text)
phone_re.fullmatch(value)

# 编译选项
re.compile(r"pattern", re.IGNORECASE)   # 忽略大小写
re.compile(r"pattern", re.MULTILINE)    # 多行 ^ $
re.compile(r"pattern", re.DOTALL)       # . 匹配换行
re.compile(r"pattern", re.VERBOSE)      # 允许注释空白

# 示例(VERBOSE 提高可读性)
pattern = re.compile(r"""
    (?P\d{4})  # 年
    -
    (?P\d{2}) # 月
""", re.VERBOSE)
m = pattern.search("2026-08")
m.group("year")     # '2026'(命名分组)

替换与回调

# 简单替换
re.sub(r"\d+", "N", "a1b2")       # 'aNbN'

# 引用分组
re.sub(r"(\w+)@(\w+)", r"\2@\1", "user@host")
# 'host@user'

# 函数回调(动态替换)
def repl(m):
    num = int(m.group())
    return str(num * 2)
re.sub(r"\d+", repl, "a1b2c3")    # 'a2b4c6'

正则性能与安全

# 1. 避免灾难性回溯
# 危险: (a+)+ 或 (a|a)+ 在特定输入下极慢
# 应对: 避免嵌套量词,尽量具体化

# 2. 编译复用
# 3. 简单匹配用字符串方法更快
#    "abc" in text / text.startswith("a")

# 4. re 模块函数 vs 编译对象
# 少量使用: re.search(...) 方便
# 循环使用: compile 后调用(快 30%+)

# 5. 验证输入边界
# fullmatch 用于完整匹配(防止部分匹配绕过)

实用案例

# 1. 提取所有数字
numbers = [int(x) for x in re.findall(r"\d+", text)]

# 2. 清洗文本(去 HTML 标签)
clean = re.sub(r"<[^>]+>", "", html_text)

# 3. 分割混合分隔符
parts = re.split(r"[;,\s]+", "a;b, c d")

# 4. 敏感信息脱敏
def mask_phone(text):
    return re.sub(r"(1[3-9]\d)\d{4}(\d{4})",
                  r"\1****\2", text)

# 5. 日志解析
pattern = re.compile(
    r"(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) "
    r"(\w+): (.*)")
for line in log_lines:
    m = pattern.match(line)
    if m:
        date, time, level, msg = m.groups()

正则表达式是文本处理的"瑞士军刀"。掌握元字符、分组、编译与替换,配合常用模式库,文本处理高效可靠。

Python CGI 编程

Python CGI 编程

CGI(Common Gateway Interface)是最早的 Web 动态页面技术:Web 服务器把请求转给 CGI 程序(如 Python 脚本),程序输出 HTML 返回。理解 CGI 有助于掌握 Web 工作原理。

工作原理

浏览器 → HTTP 请求 → Web 服务器
                        ↓
                  执行 CGI 程序(Python)
                        ↓
           程序输出 HTML(标准输出)
                        ↓
Web 服务器 → HTTP 响应 → 浏览器

# CGI 程序通过环境变量与标准输入获取请求信息
# 通过标准输出返回响应

最小 CGI 程序

#!/usr/bin/env python
# hello.py
import cgi

print("Content-Type: text/html\n")   # 头部+空行
print("")
print("

Hello, Python CGI!

") print("")

读取请求参数

import cgi

form = cgi.FieldStorage()    # 解析表单/参数

# GET: ?name=xx&age=18
# POST: 表单数据
name = form.getvalue("name", "匿名")
age = form.getvalue("age", "未知")

print("Content-Type: text/html; charset=utf-8\n")
print(f"

姓名: {name}

") print(f"

年龄: {age}

") # 多值参数 items = form.getlist("item") # 复选框 # 判断请求方法 import os method = os.environ.get("REQUEST_METHOD", "GET")

HTML 转义(XSS 防护)

import cgi
import html

# 用户输入必须转义,防止 XSS
user_input = ""
safe = html.escape(user_input)
# '<script>alert('x')</script>'

print(f"

{safe}

") # 旧式接口 # cgi.escape() 已弃用,用 html.escape()

Cookie 与 Session

import http.cookies

# 读取 Cookie
cookie_header = os.environ.get("HTTP_COOKIE", "")
cookies = http.cookies.SimpleCookie(cookie_header)
user_id = cookies.get("user_id")
if user_id:
    print(f"用户: {user_id.value}")

# 设置 Cookie(响应头)
cookie = http.cookies.SimpleCookie()
cookie["user_id"] = "12345"
cookie["user_id"]["path"] = "/"
cookie["user_id"]["max-age"] = 3600
print(cookie.output())        # Set-Cookie: ...
print("Content-Type: text/html\n")

文件上传

import cgi

form = cgi.FieldStorage()

if "file" in form:
    file_item = form["file"]
    if file_item.filename:
        # 读取上传内容
        data = file_item.file.read()
        # 保存(注意路径安全!)
        filename = file_item.filename
        with open(f"uploads/{filename}", "wb") as f:
            f.write(data)
        print("上传成功")
    else:
        print("未选择文件")

重定向与状态码

# 重定向
print("Location: /index.html\n")

# 404
print("Status: 404 Not Found")
print("Content-Type: text/html\n")
print("

404

") # 其他常用头 print("Content-Type: application/json") print("Content-Type: text/plain; charset=utf-8")

部署配置

# Apache: cgi-bin 目录配置
# ScriptAlias /cgi-bin/ /path/to/cgi-bin/
# 添加执行权限
# chmod +x hello.py

# Nginx + CGI(通过 fastcgi/fcgiwrap)

# 调试 CGI
# 1. 检查日志(服务器错误日志)
# 2. 直接命令行运行(模拟)
#    REQUEST_METHOD=GET ./hello.py
# 3. 查看输出格式是否合法(头部+空行)

现代替代方案

# CGI 已过时,现代 Python Web 用 WSGI:
# - Flask / Django / FastAPI(框架)
# - Gunicorn / uWSGI(服务器)

# Flask 示例(替代 CGI)
from flask import Flask, request
app = Flask(__name__)

@app.route("/")
def index():
    name = request.args.get("name", "匿名")
    return f"

你好, {name}

" if __name__ == "__main__": app.run() # 为何用 WSGI: # - 性能更好(常驻进程 vs 每次启动) # - 功能完整(路由/模板/会话) # - 更安全(框架内置防护)

学习价值

# 虽然 CGI 过时,但它清晰展示了:
# 1. HTTP 请求-响应模型
# 2. 服务器与程序的交互方式
# 3. 动态页面生成原理
# 4. 表单处理、Cookie、会话基础

# 理解 CGI = 理解 Web 的"最小骨架"
# 对学习 Flask/Django 帮助巨大

CGI 是 Web 编程的入门课:请求解析、响应生成、转义与 Cookie。现代开发用 Flask/Django,但 CGI 的原理不过时。

Python MySQL

Python MySQL

Python 操作 MySQL 数据库:连接、查询、增删改、事务。常用驱动:pymysql、mysql-connector-python,以及 ORM(SQLAlchemy)。

安装驱动

# pymysql(纯 Python,易装)
pip install pymysql

# 或官方驱动
pip install mysql-connector-python

# ORM(高级)
pip install sqlalchemy

连接数据库

import pymysql

# 建立连接
conn = pymysql.connect(
    host="localhost",        # 主机
    port=3306,               # 端口
    user="root",             # 用户
    password="password",     # 密码
    database="test",         # 数据库
    charset="utf8mb4",       # 编码(中文)
    cursorclass=pymysql.cursors.DictCursor,  # 字典游标
)

# 创建游标
cursor = conn.cursor()

查询数据

import pymysql

conn = pymysql.connect(...)
cursor = conn.cursor()

# 查询
cursor.execute("SELECT id, name FROM users")
results = cursor.fetchall()       # 所有行
row = cursor.fetchone()           # 单行
rows = cursor.fetchmany(5)        # 5 行

# 带参数(防 SQL 注入!)
cursor.execute(
    "SELECT * FROM users WHERE age > %s",
    (18,)
)

# 占位符: %s(注意不是 ?)
cursor.execute(
    "SELECT * FROM users WHERE name = %s AND age = %s",
    ("张三", 20)
)

cursor.close()

增删改

conn = pymysql.connect(...)
cursor = conn.cursor()

# 插入
cursor.execute(
    "INSERT INTO users(name, age) VALUES(%s, %s)",
    ("李四", 25)
)
conn.commit()          # 必须提交!
print(cursor.lastrowid)   # 自增 ID

# 批量插入(高效)
data = [("a", 1), ("b", 2), ("c", 3)]
cursor.executemany(
    "INSERT INTO users(name, age) VALUES(%s, %s)",
    data
)
conn.commit()

# 更新
cursor.execute(
    "UPDATE users SET age = %s WHERE name = %s",
    (30, "张三")
)
conn.commit()
print(cursor.rowcount)    # 影响行数

# 删除
cursor.execute(
    "DELETE FROM users WHERE age < %s",
    (18,)
)
conn.commit()

# 回滚(出错时)
try:
    cursor.execute("INSERT INTO ...", data)
    conn.commit()
except Exception:
    conn.rollback()      # 撤销
    raise

事务处理

# 事务: 一组操作要么全部成功,要么全部回滚
try:
    # 转账示例
    cursor.execute(
        "UPDATE accounts SET balance=balance-100 "
        "WHERE id=%s", (1,))
    cursor.execute(
        "UPDATE accounts SET balance=balance+100 "
        "WHERE id=%s", (2,))

    conn.commit()        # 全部成功才提交
    print("转账成功")
except Exception as e:
    conn.rollback()      # 任一失败全部回滚
    print(f"转账失败,已回滚: {e}")
finally:
    cursor.close()
    conn.close()

# 注意: 表引擎必须是 InnoDB 才支持事务

连接管理(推荐 with)

import pymysql
from contextlib import closing

# 自动关闭游标与连接
with closing(pymysql.connect(
        host="localhost", user="root",
        password="pwd", database="test",
        charset="utf8mb4")) as conn:
    with closing(conn.cursor()) as cursor:
        cursor.execute("SELECT COUNT(*) FROM users")
        print(cursor.fetchone())

SQLAlchemy ORM

from sqlalchemy import create_engine, Column, Integer, String, select
from sqlalchemy.orm import declarative_base, Session

# 连接
engine = create_engine(
    "mysql+pymysql://root:password@localhost/test",
    echo=True          # 打印 SQL(调试)
)
Base = declarative_base()

# 定义模型
class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    age = Column(Integer)

# 创建表
Base.metadata.create_all(engine)

# 增
with Session(engine) as session:
    session.add(User(name="王五", age=28))
    session.commit()

# 查
with Session(engine) as session:
    users = session.scalars(select(User).where(
        User.age > 20)).all()
    for u in users:
        print(u.name, u.age)

# 改/删
with Session(engine) as session:
    user = session.get(User, 1)
    user.age = 31
    session.delete(user)
    session.commit()

SQL 注入防护

# 永远用参数化查询(占位符)!
# ❌ 危险: 字符串拼接
name = "' OR '1'='1"
cursor.execute(f"SELECT * FROM users WHERE name='{name}'")
# 注入成功!

# ✅ 安全: 参数化
cursor.execute(
    "SELECT * FROM users WHERE name=%s",
    (name,)
)

# 规则:
# - 不用 f-string/拼接 构造 SQL
# - 用户输入一律走参数
# - 表名/列名等标识符固定,不来自用户
#   (如需动态,白名单校验)

连接池与最佳实践

# 1. 连接用完即关(或 with)
# 2. 高频操作用连接池
from dbutils.pooled_db import PooledDB
pool = PooledDB(
    creator=pymysql, maxconnections=10,
    host="localhost", user="root",
    password="pwd", database="test")
conn = pool.connection()    # 从池取

# 3. 密码不硬编码(环境变量)
import os
password = os.environ.get("DB_PASSWORD")

# 4. 处理异常
try:
    cursor.execute(sql, params)
except pymysql.MySQLError as e:
    print(f"数据库错误: {e}")

# 5. 索引: 常用查询字段建索引
# 6. 批量操作用 executemany
# 7. 大量数据分页(limit/offset)
cursor.execute("SELECT * FROM users LIMIT %s OFFSET %s",
               (page_size, offset))

Python + MySQL 是经典组合。掌握 pymysql 增删改查与事务,坚持参数化查询防注入,再进阶 SQLAlchemy ORM。

Python SMTP

Python SMTP

Python 通过 smtplib 发送邮件,配合 email 模块构造邮件内容(文本/HTML/附件)。

发送纯文本邮件

import smtplib
from email.mime.text import MIMEText
from email.header import Header

# 构造邮件
msg = MIMEText("这是一封测试邮件", "plain", "utf-8")
msg["From"] = "sender@example.com"      # 发件人
msg["To"] = "receiver@example.com"      # 收件人
msg["Subject"] = Header("邮件主题", "utf-8")

# 连接 SMTP 服务器并发送
smtp = smtplib.SMTP("smtp.example.com", 25)
smtp.login("username", "password")      # 认证
smtp.send_message(msg)
smtp.quit()
print("邮件已发送")

发送 HTML 邮件

from email.mime.text import MIMEText

html = """

欢迎注册!

点击 这里 验证你的邮箱。

""" msg = MIMEText(html, "html", "utf-8") msg["Subject"] = "注册确认" # 其余同上...

带附件

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

# 混合内容容器
msg = MIMEMultipart()
msg["From"] = "sender@example.com"
msg["To"] = "receiver@example.com"
msg["Subject"] = "月报"

# 正文
msg.attach(MIMEText("请查收附件", "plain", "utf-8"))

# 附件
with open("report.pdf", "rb") as f:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(f.read())
    encoders.encode_base64(part)          # 编码
    part.add_header(
        "Content-Disposition",
        "attachment",
        filename="report.pdf",
    )
    msg.attach(part)

# 发送
smtp = smtplib.SMTP_SSL("smtp.example.com", 465)
smtp.login("user", "pass")
smtp.send_message(msg)
smtp.quit()

常见邮箱服务器配置

# QQ 邮箱
SMTP: smtp.qq.com
端口: 465(SSL)或 587(TLS)
认证: QQ 邮箱授权码(非登录密码)
设置: 设置 → 账户 → 开启 SMTP 服务

# 163 邮箱
SMTP: smtp.163.com
端口: 465(SSL)或 25
认证: 授权码

# Gmail
SMTP: smtp.gmail.com
端口: 587(TLS)
认证: 应用专用密码

# 企业邮箱(腾讯企业邮)
SMTP: smtp.exmail.qq.com
端口: 465/587

SSL/TLS 发送

# 方式1: SMTP_SSL(直接 SSL,端口 465)
smtp = smtplib.SMTP_SSL("smtp.qq.com", 465)

# 方式2: SMTP + starttls(端口 587)
smtp = smtplib.SMTP("smtp.qq.com", 587)
smtp.starttls()          # 升级为 TLS

# 认证
smtp.login("user@qq.com", "授权码")

# 发送
smtp.send_message(msg)

# 关闭
smtp.quit()

批量发送与抄送

# 多收件人/抄送
msg["To"] = "a@example.com, b@example.com"
msg["Cc"] = "cc@example.com"

# 批量发送(复用连接,逐个 send)
recipients = ["a@x.com", "b@x.com"]
smtp = smtplib.SMTP_SSL(...)
smtp.login(...)
for to in recipients:
    msg["To"] = to
    smtp.send_message(msg)     # 每封单独 To
smtp.quit()

# 群发注意: 大量发送易被判定垃圾邮件
# 建议: 限速、个性化内容、用专门服务

异常处理

import smtplib

try:
    smtp = smtplib.SMTP_SSL("smtp.qq.com", 465)
    smtp.login("user", "authcode")
    smtp.send_message(msg)
    print("发送成功")
except smtplib.SMTPAuthenticationError:
    print("认证失败: 检查账号/授权码")
except smtplib.SMTPRecipientsRefused:
    print("收件人被拒绝")
except smtplib.SMTPException as e:
    print(f"发送失败: {e}")
finally:
    try:
        smtp.quit()
    except Exception:
        pass

封装邮件发送函数

import smtplib
from email.mime.text import MIMEText
from email.header import Header
import os

SMTP_HOST = os.environ.get("SMTP_HOST", "smtp.qq.com")
SMTP_PORT = int(os.environ.get("SMTP_PORT", "465"))
SMTP_USER = os.environ.get("SMTP_USER")
SMTP_AUTH = os.environ.get("SMTP_AUTH")   # 授权码

def send_email(to, subject, content,
               content_type="plain"):
    """发送邮件"""
    msg = MIMEText(content, content_type, "utf-8")
    msg["From"] = SMTP_USER
    msg["To"] = to
    msg["Subject"] = Header(subject, "utf-8")

    with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT) as smtp:
        smtp.login(SMTP_USER, SMTP_AUTH)
        smtp.send_message(msg)

# 使用
send_email("receiver@example.com",
           "通知", "您的订单已发货")

最佳实践

# 1. 凭据用环境变量,不硬编码
# 2. 邮件模板化(HTML 模板 + 数据填充)
# 3. 附件大小控制
# 4. 发送失败重试(带退避)
# 5. 记录发送日志
# 6. 生产环境考虑邮件服务(腾讯云/阿里云 SES)
#    或第三方(如 SendGrid)
# 7. 中文用 utf-8 编码 + Header

# 大文件附件: 放网盘发链接,勿直接附件
# 敏感内容: 确认合规与加密

Python SMTP 让程序自动发邮件:通知、报表、验证码。掌握 smtplib + email 模块,配合邮箱授权码,即可上线邮件功能。

Python 多线程

Python 多线程

多线程让程序同时处理多个任务,适合 I/O 密集场景(网络请求、文件读写)。本节介绍 threading 与相关工具。

创建线程

import threading
import time

def worker(name, delay):
    time.sleep(delay)
    print(f"{name} 完成")

# 方式1: 直接创建
t = threading.Thread(target=worker,
                     args=("任务A", 1))
t.start()          # 启动线程
t.join()           # 等待完成

# 方式2: 继承 Thread
class MyThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):              # 重写 run
        time.sleep(0.5)
        print(f"线程 {self.name} 运行中")

t = MyThread("T1")
t.start()

并发执行多个任务

import threading
import time

def task(name, seconds):
    print(f"{name} 开始")
    time.sleep(seconds)
    print(f"{name} 结束")
    return name

# 启动多个线程
threads = []
for i in range(3):
    t = threading.Thread(target=task,
                         args=(f"任务{i}", 1))
    t.start()
    threads.append(t)

# 等待全部完成
for t in threads:
    t.join()
print("全部完成")

# 对比串行: 串行需 3 秒,并行约 1 秒(I/O)

线程安全与锁

import threading

# 共享数据需要锁保护
counter = 0
lock = threading.Lock()

def increment():
    global counter
    for _ in range(10000):
        with lock:              # 加锁
            counter += 1

threads = [threading.Thread(target=increment)
           for _ in range(5)]
for t in threads: t.start()
for t in threads: t.join()
print(counter)      # 50000(无锁可能小于此值)

# 其他锁:
# threading.RLock(): 可重入锁(同线程可重复获取)
# threading.Semaphore(n): 信号量(限制并发数)
# threading.Event(): 事件(线程间通知)

线程间通信(Queue)

import threading
import queue
import time

# 线程安全队列
q = queue.Queue()

def producer():
    for i in range(5):
        q.put(f"消息{i}")      # 生产
        time.sleep(0.1)
    q.put(None)                # 结束信号

def consumer():
    while True:
        item = q.get()
        if item is None:
            break
        print(f"消费: {item}")

# 多个生产者/消费者
threading.Thread(target=producer).start()
for _ in range(2):
    threading.Thread(target=consumer).start()

ThreadPoolExecutor(推荐)

from concurrent.futures import ThreadPoolExecutor
import time

def fetch(url):
    time.sleep(1)               # 模拟请求
    return f"{url} 数据"

# 线程池: 控制并发数
with ThreadPoolExecutor(max_workers=4) as pool:
    urls = [f"url{i}" for i in range(8)]

    # 方式1: map(批量)
    results = list(pool.map(fetch, urls))

    # 方式2: submit + as_completed(按完成顺序)
    futures = [pool.submit(fetch, u) for u in urls]
    for fut in futures:
        print(fut.result())

# 8 个任务,4 并发: 约 2 秒(串行需 8 秒)

# 与 asyncio 对比:
# ThreadPoolExecutor: 简单,线程开销
# asyncio: 更高效,但需异步代码

线程局部数据

import threading

# 每个线程独立的存储
local = threading.local()

def worker(name):
    local.name = name          # 线程私有
    time.sleep(0.1)
    print(f"{local.name} 完成")

threads = [threading.Thread(target=worker,
                            args=(f"T{i}",))
           for i in range(3)]
for t in threads: t.start()
for t in threads: t.join()
# 每个线程访问自己的 local.name

守护线程

import threading
import time

def daemon_worker():
    while True:
        print("守护线程工作中...")
        time.sleep(1)

# daemon=True: 主线程结束则自动结束
d = threading.Thread(target=daemon_worker,
                     daemon=True)
d.start()

# 主线程做自己的事
time.sleep(3)
print("主线程结束")
# 守护线程随之结束(不阻塞退出)

# 应用: 心跳、监控、日志后台任务

GIL 与多进程

# GIL(全局解释器锁):
# 同一时刻只有一个线程执行 Python 字节码
# → CPU 密集任务多线程无提速!

# I/O 密集: 多线程有效(等待时释放 GIL)
# CPU 密集: 用多进程(每个进程独立 GIL)

# 多进程
from concurrent.futures import ProcessPoolExecutor

def cpu_task(n):
    return sum(i * i for i in range(n))

with ProcessPoolExecutor(max_workers=4) as pool:
    results = list(pool.map(cpu_task,
                            [10**6] * 4))

# 多进程注意:
# - 开销大(进程创建)
# - 数据传递需序列化
# - 共享状态复杂(用 Queue/Pipe)

最佳实践

# 1. 优先 ThreadPoolExecutor(简单安全)
# 2. I/O 密集用线程,CPU 密集用进程
# 3. 共享数据一律加锁
# 4. 通信用 Queue,少用共享变量
# 5. 设置 daemon 或确保 join(防僵尸)
# 6. 异常在任务内捕获(线程异常不自动打印)

# 线程内异常处理
def safe_worker():
    try:
        risky_io()
    except Exception as e:
        print(f"任务失败: {e}")

# 获取线程结果(用 Future)
with ThreadPoolExecutor() as pool:
    fut = pool.submit(fetch, "url")
    try:
        result = fut.result(timeout=5)  # 超时
    except TimeoutError:
        print("超时")

多线程是 I/O 密集任务的提速器。掌握 ThreadPoolExecutor、锁与 Queue,注意 GIL 限制(CPU 密集用进程),并发编程不再神秘。

Python XML 解析

Python XML 解析

XML 是结构化数据格式。Python 提供多种解析方式:ElementTree(推荐)、DOM、SAX,以及高性能的 lxml。

XML 示例

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book id="1">
    <title>Python 入门</title>
    <price>59.0</price>
  </book>
  <book id="2">
    <title>Python 进阶</title>
    <price>79.0</price>
  </book>
</bookstore>

ElementTree 解析(推荐)

import xml.etree.ElementTree as ET

# 从文件
tree = ET.parse("books.xml")
root = tree.getroot()

# 从字符串
root = ET.fromstring(xml_string)

# 基本访问
root.tag           # 'bookstore'
root.attrib        # {} 属性字典
root.text          # 文本(直接子文本)

# 遍历
for book in root:               # 直接子元素
    print(book.tag, book.attrib)

for book in root.iter("book"):  # 递归找所有 book
    print(book.get("id"))

# 查找
root.find("book")            # 第一个 book
root.findall("book")         # 所有 book
root.find(".//title")        # XPath 递归找 title
root.findall(".//price")     # 所有 price
book.find("title").text      # 子元素文本

读取与修改

import xml.etree.ElementTree as ET

tree = ET.parse("books.xml")
root = tree.getroot()

# 读取元素内容
for book in root.findall("book"):
    book_id = book.get("id")                 # 属性
    title = book.find("title").text          # 子元素
    price = float(book.find("price").text)
    print(f"{book_id}: {title} - {price}")

# 修改
book = root.find("book")
book.set("id", "100")                        # 改属性
book.find("title").text = "新标题"           # 改文本
book.find("price").text = "99.0"

# 删除
root.remove(book)                            # 删除子元素

# 保存
tree.write("books_new.xml", encoding="utf-8",
           xml_declaration=True)

创建 XML

import xml.etree.ElementTree as ET

# 创建根元素
root = ET.Element("bookstore")

# 添加子元素
book = ET.SubElement(root, "book")
book.set("id", "3")

title = ET.SubElement(book, "title")
title.text = "Python 高级"

price = ET.SubElement(book, "price")
price.text = "89.0"

# 转成字符串
xml_str = ET.tostring(root, encoding="unicode")
print(xml_str)

# 保存到文件
tree = ET.ElementTree(root)
tree.write("new_books.xml", encoding="utf-8",
           xml_declaration=True)

XPath 查询

import xml.etree.ElementTree as ET

root = ET.parse("books.xml").getroot()

# 常用 XPath
root.findall("book")              # 直接子 book
root.findall(".//title")          # 所有 title
root.findall("book[@id='1']")     # 属性过滤
root.findall(".//book[price>60]") # 条件(部分支持)
root.find("./book[2]")            # 第 2 个 book

# 遍历命名空间
# <ns:book xmlns:ns="http://x.com">
ns = {"ns": "http://x.com"}
root.findall("ns:book", ns)       # 带命名空间查找

DOM 解析(minidom)

from xml.dom import minidom

# 解析
doc = minidom.parse("books.xml")
root = doc.documentElement        # bookstore

# 获取元素
books = doc.getElementsByTagName("book")
for book in books:
    book_id = book.getAttribute("id")
    title = book.getElementsByTagName("title")[0]
    title_text = title.firstChild.nodeValue
    print(f"{book_id}: {title_text}")

# 与 ElementTree 对比:
# DOM 更接近标准(全树在内存)
# ElementTree 更 Pythonic,推荐日常使用

SAX 解析(流式)

# SAX: 事件驱动,适合超大文件(省内存)
import xml.sax

class BookHandler(xml.sax.ContentHandler):
    def __init__(self):
        self.current = None
        self.books = []

    def startElement(self, name, attrs):
        if name == "book":
            self.current = {"id": attrs.get("id")}
        elif name in ("title", "price") and self.current:
            self.current[name] = ""

    def characters(self, content):
        if self.current and self.current.get(
                "title") is not None:
            if "title" in self.current and \
               isinstance(self.current["title"], str) \
               and len(self.current["title"]) < 100:
                self.current["title"] += content

    def endElement(self, name):
        if name == "book" and self.current:
            self.books.append(self.current)
            self.current = None

handler = BookHandler()
xml.sax.parse("books.xml", handler)
print(handler.books)

# 使用场景: 超大 XML(GB 级)流式处理

lxml(高性能推荐)

# pip install lxml
from lxml import etree

# 解析
tree = etree.parse("books.xml")
root = tree.getroot()

# XPath 强大
root.xpath("//book[@id='2']/title/text()")
# ['Python 进阶']

# 遍历
for book in root.iter("book"):
    print(book.get("id"),
          book.findtext("title"))

# 创建
root = etree.Element("bookstore")
book = etree.SubElement(root, "book")
etree.SubElement(book, "title").text = "lxml 教程"

# 序列化
print(etree.tostring(root, pretty_print=True,
                     encoding="unicode"))

# lxml 优势: 快、XPath 完整、HTML 解析
# 与 ElementTree API 兼容(大多数场景可直接换)

安全注意

# XXE 攻击(XML 外部实体注入)!
# 恶意 XML 可读取服务器文件
# <!DOCTYPE x [<!ENTITY f SYSTEM "file:///etc/passwd">]>

# ElementTree 默认不处理外部实体(较安全)
# lxml 需禁用:
from lxml import etree
parser = etree.XMLParser(
    resolve_entities=False,   # 禁用实体解析
    no_network=True)          # 禁用网络
tree = etree.parse("data.xml", parser)

# 解析不可信 XML 的通用建议:
# - 禁用外部实体
# - 限制解析深度/大小
# - 优先 JSON(简单场景)

最佳实践

# 1. 日常解析用 ElementTree(标准库,够用)
# 2. 复杂 XPath/高性能用 lxml
# 3. 超大文件用 SAX/流式(iterparse)
# 4. 处理不可信 XML 注意 XXE
# 5. 简单数据交换优先 JSON(更轻量)

# 流式处理大文件
import xml.etree.ElementTree as ET
for event, elem in ET.iterparse("big.xml"):
    if elem.tag == "book":
        process(elem)
        elem.clear()       # 释放内存

XML 解析是数据处理常客。ElementTree 满足多数需求,lxml 更强更快,SAX 应对超大文件。按场景选择,注意安全。

Python GUI 编程(Tkinter)

Python GUI 编程(Tkinter)

Tkinter 是 Python 标准库自带的 GUI 工具包,无需安装即可创建桌面窗口程序。适合工具类应用与学习 GUI 编程。

第一个窗口

import tkinter as tk

# 创建主窗口
root = tk.Tk()
root.title("我的程序")
root.geometry("400x300")       # 宽x高

# 主循环(显示窗口)
root.mainloop()

常用控件

import tkinter as tk

root = tk.Tk()

# 标签
label = tk.Label(root, text="欢迎使用", fg="blue",
                 font=("Arial", 16))
label.pack(pady=10)

# 按钮
def on_click():
    label.config(text="按钮被点击了!")

btn = tk.Button(root, text="点击我",
                command=on_click)
btn.pack(pady=5)

# 输入框
entry = tk.Entry(root, width=30)
entry.pack(pady=5)
entry.insert(0, "默认文本")

# 文本区域
text = tk.Text(root, height=5, width=40)
text.pack(pady=5)

# 单选/复选
var = tk.IntVar()
check = tk.Checkbutton(root, text="记住我",
                       variable=var)
check.pack()

# 下拉框
import tkinter.ttk as ttk
combo = ttk.Combobox(root, values=["A", "B", "C"])
combo.pack()

root.mainloop()

布局管理

import tkinter as tk

root = tk.Tk()

# pack: 顺序排列
tk.Label(root, text="上").pack(side="top")
tk.Label(root, text="左").pack(side="left")
tk.Label(root, text="右").pack(side="right")
tk.Label(root, text="下").pack(side="bottom")

# grid: 网格布局(推荐复杂界面)
root = tk.Tk()
for r in range(3):
    for c in range(3):
        tk.Button(root, text=f"{r},{c}").grid(
            row=r, column=c, padx=5, pady=5)

# place: 绝对定位
tk.Label(root, text="定位").place(x=50, y=100)

# 扩展: sticky/expand/fill
tk.Button(root, text="填充").pack(
    fill="x", expand=True)   # 水平填充

事件绑定

import tkinter as tk

root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200,
                   bg="white")
canvas.pack()

# 鼠标事件
def on_click(event):
    canvas.create_oval(event.x-3, event.y-3,
                       event.x+3, event.y+3,
                       fill="red")

canvas.bind("", on_click)   # 左键点击

# 键盘事件
def on_key(event):
    print(f"按下: {event.keysym}")

root.bind("", on_key)

# 常用事件:
#  左键  右键
#  双击
#  移动  回车
#  按键 a

完整示例: 待办清单

import tkinter as tk
from tkinter import messagebox

class TodoApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("待办清单")
        self.root.geometry("360x400")

        # 输入区
        self.entry = tk.Entry(self.root, width=30)
        self.entry.pack(pady=10)
        self.entry.bind("", self.add_todo)

        tk.Button(self.root, text="添加",
                  command=self.add_todo).pack()

        # 列表
        self.listbox = tk.Listbox(self.root,
                                  width=42, height=15)
        self.listbox.pack(pady=10)

        # 操作按钮
        tk.Button(self.root, text="删除选中",
                  command=self.delete_todo).pack()

        self.root.mainloop()

    def add_todo(self, event=None):
        text = self.entry.get().strip()
        if text:
            self.listbox.insert(tk.END, text)
            self.entry.delete(0, tk.END)
        else:
            messagebox.showwarning("提示", "不能为空")

    def delete_todo(self):
        try:
            idx = self.listbox.curselection()[0]
            self.listbox.delete(idx)
        except IndexError:
            messagebox.showinfo("提示", "请先选中")

TodoApp()

对话框

from tkinter import messagebox, filedialog, simpledialog

# 消息框
messagebox.showinfo("信息", "操作成功")
messagebox.showwarning("警告", "磁盘空间不足")
messagebox.showerror("错误", "文件不存在")
result = messagebox.askyesno("确认", "确定删除?")

# 文件对话框
filename = filedialog.askopenfilename(
    title="选择文件", filetypes=[("文本", "*.txt")])
save_path = filedialog.asksaveasfilename()

# 输入对话框
name = simpledialog.askstring("输入", "你的名字:")
number = simpledialog.askinteger("输入", "数字:")

定时任务与动画

import tkinter as tk
import time

root = tk.Tk()
label = tk.Label(root, text="", font=("Arial", 24))
label.pack()

# 定时更新
def update_time():
    label.config(text=time.strftime("%H:%M:%S"))
    root.after(1000, update_time)   # 1秒后再调用

update_time()

# 简单动画
x = 0
ball = tk.Label(root, text="●", font=("Arial", 20))
ball.pack()

def move():
    global x
    x = (x + 5) % 300
    ball.place(x=x, y=100)
    root.after(50, move)    # 50ms 移动一次

move()
root.mainloop()

最佳实践

# 1. 长任务放线程(否则界面卡死)
import threading

def long_task():
    # 耗时操作...
    pass

tk.Button(root, text="开始",
          command=lambda: threading.Thread(
              target=long_task, daemon=True).start())

# 2. 界面更新放主线程(用队列通信)
# 3. 组件用 grid/pack 合理布局
# 4. 样式统一(颜色/字体常量)
# 5. 数据与界面分离(简单 MVC)

# 其他 GUI 框架:
# - PyQt/PySide: 强大专业
# - wxPython: 原生外观
# - Kivy: 移动端
# - 简单工具: Tkinter 够用

# 打包发布
# pip install pyinstaller
# pyinstaller --onefile --windowed app.py

Tkinter 让 Python 轻松拥有图形界面。掌握控件、布局与事件,配合线程处理耗时任务,即可开发实用桌面工具。

Python2.x 与 3.x 版本区别

Python2.x 与 3.x 版本区别

Python 3 是 Python 2 的重大升级,不向后兼容。理解两者的区别,有助于阅读旧代码与正确迁移。Python 2 已于 2020 年停止维护。

核心差异总览

# 1. print 语句 vs 函数
# Python 2
print "hello"
# Python 3
print("hello")

# 2. 整数除法
# Python 2: 3 / 2 = 1(整数除)
# Python 3: 3 / 2 = 1.5(真除法)
#           3 // 2 = 1(整除)

# 3. 字符串与 Unicode
# Python 2: str(字节) + unicode(文本)
# Python 3: str(文本) + bytes(字节)
# 默认源码编码: ASCII → UTF-8

语法差异

# 1. 异常语法
# Python 2
try:
    pass
except Exception, e:      # 逗号语法
    print e
# Python 3
try:
    pass
except Exception as e:    # as 语法
    print(e)

# 2. 输入
# Python 2: raw_input() 返回 str, input() 会 eval!
# Python 3: input() 统一返回 str(安全)

# 3. range vs xrange
# Python 2: range() 返回列表, xrange() 惰性
# Python 3: range() 惰性(等价 xrange),无 xrange

# 4. 比较
# Python 2: 不同类型可比较(如 1 < "a")
# Python 3: 不同类型比较报错(更安全)

数据类型差异

# 1. 长整数
# Python 2: int + long(大数自动转 long)
# Python 3: 统一 int(任意精度,无 long)

# 2. 字典
# Python 2: 无序
# Python 3.7+: 保持插入顺序

# 3. 迭代器
# Python 2: dict.keys() 返回列表
# Python 3: dict.keys() 返回视图(省内存)
# 遍历中修改需 list(dict.keys())

# 4. 字节 vs 文本
# Python 2: "abc" 是字节; u"abc" 是文本
# Python 3: "abc" 是文本; b"abc" 是字节

模块与库变化

# 1. 模块重命名
# Python 2 → Python 3
# ConfigParser → configparser
# Queue → queue
# StringIO → io
# urllib2 → urllib.request
# Tkinter → tkinter
# __builtin__ → builtins

# 2. 函数移动
# map/filter/zip 返回迭代器(2 返回列表)
# reduce 移入 functools

# 3. 标准库删除
# 部分模块移除或改版(需替换方案)

其他变化

# 1. 元类语法
# Python 2: __metaclass__ = Meta
# Python 3: class C(metaclass=Meta)

# 2. 超级调用
# Python 2: super(Class, self).method()
# Python 3: super().method()

# 3. 非本地变量
# Python 2 无 nonlocal; 3 引入
def outer():
    x = 0
    def inner():
        nonlocal x   # 3 才有
        x += 1

# 4. 解包扩展
# Python 3: a, *b, c = [1,2,3,4]

# 5. f-string / dataclass / walrus
# Python 3.6+: f"{x}"
# Python 3.8+: := 海象运算符
# Python 3.10+: match-case
# Python 3.12+: 类型语法增强

迁移建议

# 1. 新项目直接用 Python 3(无理由用 2)
# 2. 旧项目迁移工具: 2to3
python -m lib2to3 -w old_script.py
# 3. 兼容写法(2/3 通用)
from __future__ import (
    print_function, division,
    unicode_literals)
# 4. 用 six/future 库处理兼容
import six
six.moves.range(5)

# 5. 检查依赖: 确认第三方库支持 3
# 6. 字符串/字节处理是迁移最大难点
#    - 明确 str 与 bytes 的边界
#    - 文件读写显式指定编码

# 迁移优先级:
# 1. print/除法/异常语法(自动工具可改)
# 2. 字符串编码(人工检查重点)
# 3. 第三方库依赖(确认版本)
# 4. 测试充分(行为差异)

实践检查清单

# 从 2 迁到 3 时的常见问题:
# [ ] print 是否都是函数形式
# [ ] 整数除法是否符合预期(用 // 或 float)
# [ ] 字符串 vs 字节是否混淆
# [ ] range 是否有索引操作(需 list)
# [ ] dict.keys() 是否有修改遍历
# [ ] 异常语法是否用 as
# [ ] 模块导入名是否更新
# [ ] 编码声明与文件读写
# [ ] 第三方依赖兼容性
# [ ] 正则字节模式匹配

# 验证工具:
# python -W error::DeprecationWarning script.py
# 可发现 2 的兼容警告

Python 3 是唯一被积极维护的版本。理解 2→3 的差异,迁移旧代码时有章可循;新代码永远选择 Python 3。

Python IDE

Python IDE

好的开发环境显著提升效率。本节介绍主流 Python IDE/编辑器,以及开发环境的配置技巧。

IDE 对比

# PyCharm(专业 IDE)
# - 功能全: 调试/重构/数据库/远程
# - 社区版免费(够用),专业版付费
# - 适合: 大型项目、专业开发

# VS Code(轻量编辑器)
# - 免费开源,插件丰富
# - Python + Pylance 体验极佳
# - 适合: 全栈、轻量开发、多数场景

# Jupyter Notebook
# - 交互式: 代码/文本/图表混合
# - 适合: 数据分析、教学、探索

# 其他:
# - Sublime/Atom(轻量)
# - Spyder(科学计算)
# - IDLE(自带,入门)
# - Thonny(教学,断点可视化)

VS Code 配置

# 1. 安装扩展
# - Python(Microsoft)
# - Pylance(类型检查/补全)
# - Jupyter(Notebook 支持)
# - Python Debugger

# 2. 选择解释器
# Ctrl+Shift+P → Python: Select Interpreter
# 选择虚拟环境

# 3. 设置(settings.json 片段)
{
  "python.linting.enabled": true,
  "python.linting.pylintEnabled": true,
  "python.formatting.provider": "black",
  "editor.formatOnSave": true,
  "python.analysis.typeCheckingMode": "basic"
}

# 4. 调试
# 添加 launch.json
# 断点 → F5 调试

PyCharm 配置

# 1. 创建项目时选择虚拟环境
# 2. 解释器: Settings → Project → Python Interpreter
# 3. 常用快捷键
# Ctrl+Alt+L    格式化代码
# Ctrl+Shift+F10 运行
# Ctrl+Shift+F9  调试
# Ctrl+Alt+Shift+↑ 重构
# Shift+Enter   新行

# 4. 代码检查
# Alt+Enter 快速修复
# 自动提示潜在问题

# 5. 调试器
# 断点、表达式求值、变量查看
# 条件断点、异常断点

工具链配置

# 代码格式化: black
pip install black
black my_script.py          # 自动格式化

# 代码检查: ruff(快速)
pip install ruff
ruff check .                # 检查
ruff check --fix .          # 自动修复

# 类型检查: mypy
pip install mypy
mypy my_script.py

# 一键配置(推荐组合)
# .pre-commit-config.yaml
# - black 格式化
# - ruff 检查
# - mypy 类型

Jupyter 使用

# 安装
pip install jupyter

# 启动
jupyter notebook        # 传统界面
jupyter lab             # 现代界面

# 快捷键
Shift+Enter   运行并前进
Esc → A/B     上方/下方插入
Esc → M/Y     单元格转 Markdown/代码
Tab           补全

# 常用魔法命令
%time          计时
%timeit        多次计时
%matplotlib inline  内嵌图表
%%writefile    写文件
%run script.py 运行脚本

调试技巧

# 1. 断点调试(IDE)
# 2. print 调试(简单场景)
# 3. logging 调试(生产环境)
# 4. pdb 命令行调试
import pdb
pdb.set_trace()        # 设置断点
# 运行到此处进入交互调试
# n 下一步 / s 进入函数 / c 继续 / q 退出
# p 变量名 打印变量

# 5. 异常追踪
# 捕获时打印完整堆栈
import traceback
try:
    risky()
except Exception:
    traceback.print_exc()

# 6. ipdb(更好的 pdb)
# pip install ipdb
# 有补全与高亮

虚拟环境与依赖管理

# venv
python -m venv .venv
source .venv/bin/activate     # Linux/macOS
.venv\Scripts\activate       # Windows
pip install -r requirements.txt

# poetry(现代依赖管理)
pip install poetry
poetry new myproject
poetry add requests
poetry run python main.py

# uv(超快速)
pip install uv
uv venv
uv pip install -r requirements.txt
uv add requests

# conda(科学计算)
conda create -n env python=3.11
conda activate env

最佳实践

# 1. 项目级虚拟环境(隔离依赖)
# 2. 格式化/检查/类型 一站式配置
# 3. 用调试器而非 print(高效定位)
# 4. 快捷键熟练(提升操作效率)
# 5. 代码片段与模板(常用模式)
# 6. 版本控制集成(Git 面板)
# 7. 主题与字体(护眼舒适)

# 推荐新手路线:
# IDLE/Jupyter 入门 → VS Code 或 PyCharm 深入
# 数据分析 → Jupyter + VS Code

工具是效率放大器。选一个主力 IDE 并配置到位(格式化+检查+调试),配合虚拟环境,开发体验大幅提升。

Python JSON

Python JSON

JSON 是现代数据交换的标准格式。Python 通过 json 模块实现 JSON 的解析与生成,与字典/列表无缝转换。

基本转换

import json

# 字典 → JSON 字符串
data = {"name": "Python", "age": 30,
        "tags": ["web", "ai"]}
json_str = json.dumps(data)
print(json_str)
# '{"name": "Python", "age": 30, "tags": ["web", "ai"]}'

# JSON 字符串 → Python 对象
text = '{"name": "Python", "age": 30}'
data = json.loads(text)
print(data["name"])       # 'Python'
print(type(data))         # <class 'dict'>

文件读写

import json

# 写入文件
data = {"users": [{"name": "张三", "age": 25}]}
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False,
              indent=2)          # 美化缩进

# 读取文件
with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# 关键参数:
# ensure_ascii=False: 中文原样保存(不转 \uXXXX)
# indent=2: 格式化缩进(可读)
# sort_keys=True: 键排序(一致输出)

类型映射

# Python → JSON
dict        → object
list/tuple  → array
str         → string
int/float   → number
True/False  → true/false
None        → null

# JSON → Python(反向)
# 注意: tuple 转 JSON 变 array,读回是 list

import json
d = json.dumps({"t": (1, 2, 3)})
# '{"t": [1, 2, 3]}'
json.loads(d)["t"]      # [1, 2, 3](list!)

处理中文

import json

data = {"name": "中国"}

# 默认: 中文转义为 \u 序列
json.dumps(data)
# '{"name": "\u4e2d\u56fd"}'

# 保持可读
json.dumps(data, ensure_ascii=False)
# '{"name": "中国"}'

# 读取时自动解码(无需特殊处理)
text = '{"name": "\u4e2d\u56fd"}'
json.loads(text)["name"]      # '中国'

复杂对象序列化

import json
from datetime import datetime

# 自定义类型需要转换
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 方式1: 自定义函数
def user_to_dict(user):
    return {"name": user.name, "age": user.age}

u = User("张三", 25)
json.dumps(u, default=user_to_dict)
# '{"name": "张三", "age": 25}'

# 方式2: 默认处理 datetime
def default_handler(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    if hasattr(obj, "__dict__"):
        return obj.__dict__
    return str(obj)

data = {"time": datetime.now()}
json.dumps(data, default=default_handler)

# 方式3: 对象自带 to_json
class User:
    def to_json(self):
        return {"name": self.name, "age": self.age}

json.dumps(u, default=lambda o: o.to_json())

错误处理

import json

# 解析失败
try:
    data = json.loads('{"invalid": }')
except json.JSONDecodeError as e:
    print(f"JSON 解析错误: {e}")
    print(f"位置: 行 {e.lineno}, 列 {e.colno}")

# 常见错误:
# - 尾逗号: {"a": 1,}(不允许!)
# - 单引号: {'a': 1}(必须双引号!)
# - 注释: 不支持
# - 尾随内容: {"a":1} extra

# 宽松解析技巧(不推荐,先修数据)
# 用 ast.literal_eval 处理 Python 风格字面量
import ast
data = ast.literal_eval("{'a': 1}")   # 仅安全字面量

JSON Lines(逐行 JSON)

# 大数据: 每行一个 JSON 对象
# data.jsonl
# {"id": 1, "name": "a"}
# {"id": 2, "name": "b"}

import json

# 写入
with open("data.jsonl", "w", encoding="utf-8") as f:
    for item in items:
        f.write(json.dumps(item,
                ensure_ascii=False) + "\n")

# 读取
with open("data.jsonl", "r", encoding="utf-8") as f:
    for line in f:
        if line.strip():
            item = json.loads(line)
            print(item["name"])

# 适用: 日志、流式处理、百万级数据

网络 API 中的 JSON

import json
import urllib.request

# 请求 API 并解析 JSON
url = "https://api.example.com/data"
with urllib.request.urlopen(url) as resp:
    data = json.loads(resp.read().decode("utf-8"))

# 用 requests(更常用)
import requests
resp = requests.get(url, timeout=5)
data = resp.json()          # 自动解析 JSON
print(data)

# 发送 JSON
resp = requests.post(url,
    json={"name": "张三"},   # 自动转 JSON
    headers={"Authorization": "Bearer xxx"})

最佳实践

# 1. 读写文件指定 encoding="utf-8"
# 2. 中文 ensure_ascii=False 保持可读
# 3. 数据结构化校验(schema)
#    - jsonschema 库
#    - 或 pydantic(现代推荐)
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

user = User.model_validate_json(
    '{"name": "张三", "age": 25}')

# 4. 解析不可信 JSON 限制大小/深度
# 5. 性能: 大量解析用 orjson(更快)
# import orjson
# orjson.loads / orjson.dumps

实用案例

# 1. 配置管理
with open("config.json", encoding="utf-8") as f:
    config = json.load(f)
host = config.get("host", "localhost")

# 2. 数据导出/导入
# 数据库记录 → JSON(方便交换)

# 3. 日志结构化
import logging
log_entry = {
    "time": datetime.now().isoformat(),
    "level": "ERROR",
    "message": "请求失败",
    "request_id": "abc123",
}
print(json.dumps(log_entry, ensure_ascii=False))
# 便于日志系统(ELK)采集分析

JSON 是 Python 与世界交互的"通用语言"。掌握 dump/load 与参数细节,配合文件读写与 API 使用,数据交换畅通无阻。

Python 100例

Python 100例

实践出真知。本节精选 20 个经典编程练习(涵盖基础、算法、数据处理),每个都配有解法与思路。建议先自己动手,再看答案。

1-5: 基础练习

# 1. 判断奇偶
def is_odd(n):
    return n % 2 == 1

# 2. 交换两个变量
a, b = 5, 10
a, b = b, a

# 3. 判断闰年
def is_leap(year):
    return (year % 4 == 0 and year % 100 != 0) \
        or year % 400 == 0

# 4. 计算阶乘
def factorial(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result
# 或: from math import factorial

# 5. 斐波那契数列
def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a
# fib(10) → 55

6-10: 字符串与列表

# 6. 判断回文
def is_palindrome(s):
    s = s.lower().replace(" ", "")
    return s == s[::-1]

# 7. 字符串反转
s[::-1]

# 8. 统计字符出现次数
from collections import Counter
Counter("hello").most_common(1)

# 9. 列表去重
list(set([1, 2, 2, 3]))
# 保持顺序
list(dict.fromkeys([1, 2, 2, 3]))

# 10. 找出最大/次大
nums = [3, 1, 4, 1, 5, 9, 2, 6]
sorted(set(nums))[-2:]    # 最大两个

# 或遍历找次大
def second_max(nums):
    first = second = float("-inf")
    for n in nums:
        if n > first:
            second = first
            first = n
        elif n > second:
            second = n
    return second

11-15: 数学与算法

# 11. 判断素数
def is_prime(n):
    if n < 2: return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0: return False
    return True

# 12. 最大公约数/最小公倍数
import math
math.gcd(12, 18)          # 6
math.lcm(12, 18)          # 36

# 13. 冒泡排序
def bubble_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        for j in range(n - 1 - i):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

# 14. 二分查找
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

# 15. 两数之和(找下标)
def two_sum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        if target - n in seen:
            return [seen[target - n], i]
        seen[n] = i
    return []
# two_sum([2,7,11,15], 9) → [0, 1]

16-20: 数据处理与实用

# 16. 词频统计
from collections import Counter
text = "the quick brown fox the lazy dog"
words = text.split()
top = Counter(words).most_common(3)

# 17. 字典按键/值排序
d = {"b": 2, "a": 3, "c": 1}
sorted(d.items())                    # 按键
sorted(d.items(), key=lambda x: x[1])  # 按值

# 18. 扁平化嵌套列表
def flatten(lst):
    result = []
    for item in lst:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result
flatten([1, [2, [3, 4], 5], 6])  # [1,2,3,4,5,6]

# 19. 生成器: 无限序列
def even_numbers():
    n = 0
    while True:
        yield n
        n += 2
gen = even_numbers()
next(gen)   # 0
next(gen)   # 2

# 20. 日期工具
from datetime import datetime, timedelta
days_ago = datetime.now() - timedelta(days=7)
# 格式化
datetime.now().strftime("%Y-%m-%d %H:%M")

21-25: 进阶算法

# 21. 快速排序
def quicksort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    mid = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + mid + quicksort(right)

# 22. 二分/快慢指针找中间
# 链表找中点(快慢指针)
def middle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
    return slow

# 23. 最长公共前缀
def longest_common_prefix(strs):
    if not strs: return ""
    prefix = strs[0]
    for s in strs[1:]:
        while not s.startswith(prefix):
            prefix = prefix[:-1]
            if not prefix: return ""
    return prefix

# 24. 斐波那契(DP 记忆化)
from functools import lru_cache
@lru_cache(maxsize=None)
def fib_dp(n):
    return n if n < 2 else fib_dp(n-1) + fib_dp(n-2)

# 25. 滑动窗口最大和
def max_subarray_sum(nums, k):
    window = sum(nums[:k])
    result = window
    for i in range(k, len(nums)):
        window += nums[i] - nums[i - k]
        result = max(result, window)
    return result
# max_subarray_sum([2,1,5,1,3,2], 3) → 9

26-30: 文件与系统

# 26. 读取 CSV 汇总
import csv
with open("data.csv", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    total = sum(float(row["price"])
                for row in reader)

# 27. 目录遍历
from pathlib import Path
for p in Path(".").glob("**/*.py"):
    print(p)

# 28. 文件去重
seen = set()
with open("out.txt", "w", encoding="utf-8") as out:
    for line in open("in.txt", encoding="utf-8"):
        if line not in seen:
            seen.add(line)
            out.write(line)

# 29. 并发下载(简单)
from concurrent.futures import ThreadPoolExecutor
import urllib.request

def download(url):
    with urllib.request.urlopen(url) as r:
        return len(r.read())

urls = ["https://example.com"] * 5
with ThreadPoolExecutor(max_workers=5) as pool:
    sizes = list(pool.map(download, urls))

# 30. 定时任务
import time
while True:
    do_job()
    time.sleep(3600)   # 每小时一次

练习建议

# 1. 先手写,再看答案(记忆更深)
# 2. 每个例子尝试多种解法(对比优劣)
# 3. 改写参数/边界条件(测试理解)
# 4. 用测试验证
import unittest

class TestPrime(unittest.TestCase):
    def test_is_prime(self):
        self.assertTrue(is_prime(17))
        self.assertFalse(is_prime(18))

# 5. 进阶题库:
# - LeetCode(算法)
# - 菜鸟教程 Python 100 例(全量)
# - 牛客网(面试题)
# - Project Euler(数学编程)

练习是学习的加速器。把每道题"讲给别人听"(费曼技巧),或写成博客,理解会更深。编程是练出来的,不是看出来的。

Python2.x 教程

Python2.x 教程(总结)

本教程围绕 Python 语言的核心知识展开,虽以 Python 3 为主,但绝大多数概念同样适用于 Python 2.x(注意差异章节)。本节做整体回顾,并给出进一步学习路线。

核心知识回顾

# 基础
- 语法: 缩进、注释、变量、类型
- 数据类型: int/float/str/bool
- 容器: list/tuple/dict/set
- 运算: 算术/比较/逻辑/位

# 流程
- 条件: if/elif/else, 三元表达式
- 循环: for/while, break/continue/else
- 推导式: 列表/字典/集合

# 函数与模块
- 函数: 参数/返回值/作用域/lambda
- 装饰器/生成器/闭包
- 模块/包/标准库

# 数据处理
- 字符串/列表/字典操作
- 文件 I/O/pathlib
- JSON/XML/正则

# 进阶
- 面向对象: 类/继承/多态/魔术方法
- 异常处理: try/except/finally
- 多线程/多进程
- 网络: SMTP/CGI/HTTP

# 应用
- 数据库: pymysql/SQLAlchemy
- GUI: Tkinter
- IDE 与调试工具

实战能力清单

# 学完本教程,你应该能:
# 1. 写脚本处理文件与数据
# 2. 写爬虫抓取网页信息
# 3. 操作数据库(增删改查)
# 4. 写自动化脚本(批处理/定时)
# 5. 开发简单 GUI 工具
# 6. 用 JSON/XML 做数据交换
# 7. 处理并发任务(线程池)
# 8. 面向对象设计程序结构
# 9. 异常处理保证健壮性
# 10. 用正则处理文本

# 自测项目:
# - 命令行待办工具(文件存储)
# - 网页爬虫(requests + 解析)
# - 数据分析脚本(pandas 可选)
# - 桌面小工具(Tkinter)
# - 邮件自动发送脚本

学习路线进阶

# 方向1: Web 开发
# Flask → FastAPI → Django
# HTML/CSS/JS 基础

# 方向2: 数据分析
# NumPy → Pandas → Matplotlib
# 统计学基础

# 方向3: 人工智能
# 数学基础(线性代数/微积分)
# scikit-learn → PyTorch/TensorFlow
# 机器学习/深度学习

# 方向4: 自动化与运维
# 脚本/爬虫/自动化测试
# 服务器/容器(Docker)

# 方向5: 面试准备
# 算法(LeetCode)
# 数据结构
# 项目实战(简历)

资源推荐

# 官方文档(第一手资料)
# https://docs.python.org

# 中文教程
# 菜鸟教程(runoob.com)
# 廖雪峰 Python 教程

# 进阶
# Python Cookbook(进阶技巧)
# Fluent Python(流畅的 Python)

# 实践平台
# LeetCode / 牛客网
# GitHub(阅读优秀源码)
# PyPI(探索第三方库)

学习建议

# 1. 动手>阅读: 每章代码自己敲
# 2. 项目驱动: 边做项目边学
# 3. 坚持练习: 每天写点代码
# 4. 善用搜索: 错误信息/问题定位
# 5. 阅读源码: 学习优秀代码风格
# 6. 参与社区: Stack Overflow/GitHub
# 7. 记录总结: 博客/笔记沉淀知识

# 编程学习曲线:
# 入门(语法) → 熟练(套路) → 精通(设计)
# 每个阶段都需要大量实践支撑

Python 是通往"自动化与 AI"的钥匙。本教程为你打下了坚实基础,接下来选择一个方向深耕,在实践中不断成长。祝你编码愉快!

第 1 / 37 节