Python 全面入门:从核心语法到工程实践

Python 是一门语法简洁、生态丰富、应用范围广泛的编程语言。它既适合初学者学习编程,也被大量应用于 Web 开发、数据分析、人工智能、自动化运维、网络爬虫、测试开发和科学计算等领域。

本文以现代 Python 3 为基础,从运行环境、核心语法、函数、面向对象、异常处理、文件操作,一直讲到虚拟环境、测试、并发和项目结构,帮助你建立一套完整的 Python 知识体系。


1. Python 是什么

Python 是一种通用型高级编程语言,强调代码的可读性和开发效率。

所谓"通用型",是指 Python 并不局限于某一种开发场景。它可以用来编写网站后端、自动化脚本、数据分析程序、机器学习模型、桌面工具和测试程序。

需要区分两个概念:

  • Python:编程语言及其语法规范。
  • CPython:最常用的 Python 解释器实现,主要使用 C 语言编写。

我们平时从 Python 官网下载安装的版本,通常就是 CPython。

Python 程序运行时,源代码通常会先被编译成字节码,再由 Python 虚拟机执行。因此,把 Python 简单理解成"解释型语言"没有问题,但它的实际运行过程并不是逐字符直接解释。

一个最简单的 Python 程序如下:

python 复制代码
print("Hello, Python!")

与很多编程语言相比,Python 不需要编写复杂的入口类和类型声明,非常适合快速实现想法。


2. Python 的特点

2.1 语法简洁

Python 使用缩进表示代码块,不需要使用大括号。

python 复制代码
age = 20

if age >= 18:
    print("已成年")
else:
    print("未成年")

2.2 可读性较高

Python 代码通常接近自然语言:

python 复制代码
users = ["Alice", "Bob", "Charlie"]

for user in users:
    print(user)

2.3 动态类型

定义变量时不需要显式声明类型:

python 复制代码
value = 100
value = "Python"

变量本身没有固定类型,它只是引用某个对象。

不过,Python 仍然属于强类型语言。不同类型之间不会总是自动转换:

python 复制代码
age = 18

# TypeError:字符串不能直接和整数相加
message = "年龄:" + age

应该显式转换:

python 复制代码
message = "年龄:" + str(age)

或者使用格式化字符串:

python 复制代码
message = f"年龄:{age}"

2.4 跨平台

大多数 Python 程序可以运行在 Windows、Linux 和 macOS 上。

但涉及以下内容时,仍然需要处理平台差异:

  • 文件路径
  • Shell 命令
  • 文件权限
  • 系统服务
  • 操作系统专有接口

推荐使用 pathlib 处理文件路径,减少平台差异。

2.5 标准库丰富

Python 自带大量标准库,可以处理:

  • 文件与目录
  • 日期和时间
  • JSON、CSV
  • 正则表达式
  • 数据压缩
  • 网络请求基础能力
  • 并发编程
  • 日志记录
  • 单元测试
  • SQLite 数据库

这也是 Python 常被称为"自带电池"的原因。

2.6 第三方生态丰富

Python Package Index,也就是 PyPI,提供了大量第三方包,例如:

  • requests:HTTP 请求
  • fastapi:Web API
  • django:Web 应用开发
  • numpy:数值计算
  • pandas:数据处理
  • matplotlib:数据可视化
  • scikit-learn:机器学习
  • pytorch:深度学习
  • pytest:自动化测试

2.7 Python 的不足

Python 也不是所有场景下的最佳选择。

主要不足包括:

  1. 在纯计算密集型任务中,普通 Python 代码的运行速度通常不如 C、C++、Rust 等编译型语言。
  2. 动态类型虽然提高了开发效率,但部分错误只能在运行时暴露。
  3. 不同项目之间容易出现依赖版本冲突,因此必须重视虚拟环境。
  4. Python 不是浏览器前端和原生移动端开发的主流语言。
  5. 将 Python 应用打包成完全独立的桌面程序时,体积和兼容性处理可能比较复杂。

在真实项目中,选择语言需要结合业务场景、团队能力、性能要求和部署环境,而不是只看语法是否简单。


3. Python 的应用领域

3.1 Web 开发

Python 可以用于开发网站后端和 API 服务。

常见框架包括:

  • Django
  • Flask
  • FastAPI

适合开发:

  • 内容管理系统
  • 企业管理后台
  • REST API
  • 微服务
  • 数据服务
  • 人工智能接口服务

3.2 数据分析

Python 可以读取、清洗、转换和分析大量数据。

常用工具包括:

  • NumPy
  • Pandas
  • Matplotlib
  • Jupyter
  • Polars

3.3 人工智能与机器学习

Python 是人工智能领域最常见的编程语言之一。

常见工具包括:

  • Scikit-learn
  • PyTorch
  • TensorFlow
  • Transformers
  • OpenCV

3.4 自动化脚本

Python 很适合编写自动化程序,例如:

  • 批量重命名文件
  • 处理 Excel 和 CSV
  • 定时生成报表
  • 调用外部 API
  • 自动发送通知
  • 批量转换图片
  • 检查服务器状态

3.5 网络爬虫

常用工具包括:

  • Requests
  • Beautiful Soup
  • Scrapy
  • Playwright

编写爬虫时,需要遵守目标网站的服务条款、访问频率限制、版权规则以及当地法律法规。

3.6 自动化测试

Python 可以用于:

  • 接口测试
  • Web UI 测试
  • 单元测试
  • 集成测试
  • 性能测试脚本
  • 测试数据构造

3.7 运维与云计算

Python 经常用于:

  • 日志分析
  • 服务巡检
  • 配置管理
  • 云资源管理
  • CI/CD 脚本
  • 容器和 Kubernetes 工具开发

4. 安装 Python 与运行第一个程序

4.1 下载 Python

可以从 Python 官网下载安装程序:

Python 官方下载页面

在 Windows 上安装时,建议勾选:

text 复制代码
Add Python to PATH

4.2 检查安装结果

Windows PowerShell:

powershell 复制代码
py --version

macOS 或 Linux:

bash 复制代码
python3 --version

如果输出类似下面的内容,说明 Python 已经可以使用:

text 复制代码
Python 3.x.x

4.3 进入交互式解释器

Windows:

powershell 复制代码
py

macOS 或 Linux:

bash 复制代码
python3

进入后可以直接执行 Python 代码:

python 复制代码
>>> 1 + 2
3

>>> print("Hello")
Hello

退出解释器:

python 复制代码
exit()

4.4 编写第一个 Python 文件

创建 hello.py

python 复制代码
name = input("请输入你的名字:")
print(f"你好,{name}!欢迎学习 Python。")

运行程序:

Windows:

powershell 复制代码
py hello.py

macOS 或 Linux:

bash 复制代码
python3 hello.py

4.5 Python 程序的入口

一个常见的 Python 文件结构如下:

python 复制代码
def main():
    print("程序开始运行")


if __name__ == "__main__":
    main()

当文件被直接运行时,__name__ 的值是 "__main__",因此会调用 main()

当这个文件被其他模块导入时,入口代码不会自动执行。


5. Python 的基本语法

5.1 使用缩进划分代码块

Python 通常使用四个空格缩进:

python 复制代码
score = 90

if score >= 60:
    print("考试通过")
    print("可以进入下一阶段")

下面的写法会产生缩进错误:

python 复制代码
if score >= 60:
print("考试通过")

同一个代码块中不要混用 Tab 和空格。

5.2 注释

单行注释使用 #

python 复制代码
# 计算商品总价
total = price * quantity

函数、类和模块说明通常使用文档字符串:

python 复制代码
def add(a, b):
    """返回两个数的和。"""
    return a + b

可以读取文档字符串:

python 复制代码
print(add.__doc__)

5.3 一行只写一条语句

Python 虽然允许使用分号:

python 复制代码
a = 1; b = 2

但通常不推荐这样写。

推荐写成:

python 复制代码
a = 1
b = 2

5.4 命名规则

变量名可以包含:

  • 字母
  • 数字
  • 下划线

但不能以数字开头。

python 复制代码
user_name = "Alice"
user2 = "Bob"

不合法的变量名:

python 复制代码
# 不能以数字开头
2user = "Alice"

常见命名习惯:

类型 命名方式 示例
变量 小写下划线 user_name
函数 小写下划线 get_user()
大驼峰 UserService
常量 大写下划线 MAX_RETRY_COUNT
内部属性 单下划线开头 _cache

6. 变量与数据类型

6.1 变量

Python 变量不需要提前声明:

python 复制代码
name = "Python"
age = 30
price = 99.9
enabled = True

查看变量类型:

python 复制代码
print(type(name))
print(type(age))
print(type(price))
print(type(enabled))

6.2 整数

python 复制代码
count = 100
temperature = -5
binary_value = 0b1010
hex_value = 0xFF

Python 整数可以表示很大的数:

python 复制代码
large_number = 10 ** 100
print(large_number)

6.3 浮点数

python 复制代码
price = 19.99
ratio = 0.85

浮点数采用二进制表示,因此部分十进制小数无法被精确表示:

python 复制代码
print(0.1 + 0.2)

结果可能是:

text 复制代码
0.30000000000000004

涉及金额精确计算时,应考虑使用 Decimal

python 复制代码
from decimal import Decimal

result = Decimal("0.1") + Decimal("0.2")
print(result)

输出:

text 复制代码
0.3

注意:构造 Decimal 时推荐传入字符串,而不是浮点数。

6.4 布尔值

python 复制代码
is_admin = True
is_deleted = False

以下值通常会被视为假:

  • False
  • None
  • 0
  • 0.0
  • ""
  • []
  • {}
  • set()

示例:

python 复制代码
users = []

if not users:
    print("用户列表为空")

6.5 字符串

python 复制代码
name = "Python"
message = 'Hello'
description = """这是一个
可以换行的字符串"""

常见操作:

python 复制代码
text = "  Hello Python  "

print(text.strip())
print(text.lower())
print(text.upper())
print(text.replace("Python", "World"))
print(text.startswith("  Hello"))
print("Python" in text)

字符串切片:

python 复制代码
text = "Python"

print(text[0])
print(text[-1])
print(text[0:3])
print(text[::-1])

输出:

text 复制代码
P
n
Pyt
nohtyP

格式化字符串:

python 复制代码
name = "Alice"
age = 20

message = f"姓名:{name},年龄:{age}"
print(message)

格式化数字:

python 复制代码
price = 1234.5678

print(f"{price:.2f}")
print(f"{price:,.2f}")

输出:

text 复制代码
1234.57
1,234.57

6.6 空值 None

None 表示"没有值"或"值不存在"。

python 复制代码
result = None

if result is None:
    print("暂时没有结果")

判断 None 时推荐使用:

python 复制代码
value is None
value is not None

不要写成:

python 复制代码
value == None

6.7 类型转换

python 复制代码
age_text = "18"
age = int(age_text)

price = float("19.99")
message = str(100)
numbers = list((1, 2, 3))

转换可能失败:

python 复制代码
value = int("abc")

这会抛出 ValueError

6.8 可变对象与不可变对象

常见不可变对象:

  • int
  • float
  • bool
  • str
  • tuple
  • frozenset
  • None

常见可变对象:

  • list
  • dict
  • set

示例:

python 复制代码
numbers = [1, 2, 3]
numbers.append(4)

print(numbers)

列表对象本身被修改了。

字符串不能原地修改:

python 复制代码
text = "Python"
text = text + " 3"

这里创建了新的字符串对象,然后让 text 指向它。


7. 运算符

7.1 算术运算符

python 复制代码
a = 10
b = 3

print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a // b)
print(a % b)
print(a ** b)

其中:

  • /:普通除法
  • //:向下取整除法
  • %:取余
  • **:幂运算

7.2 比较运算符

python 复制代码
print(10 > 5)
print(10 >= 10)
print(10 == 10)
print(10 != 5)

Python 支持连续比较:

python 复制代码
age = 20

if 18 <= age <= 60:
    print("年龄在指定范围内")

7.3 逻辑运算符

python 复制代码
age = 20
has_permission = True

if age >= 18 and has_permission:
    print("允许访问")

逻辑运算符包括:

  • and
  • or
  • not

7.4 成员运算符

python 复制代码
roles = ["admin", "editor"]

print("admin" in roles)
print("guest" not in roles)

7.5 身份运算符

is 判断两个变量是否引用同一个对象:

python 复制代码
a = []
b = a
c = []

print(a is b)
print(a is c)
print(a == c)

输出:

text 复制代码
True
False
True

区别如下:

  • ==:比较值是否相等。
  • is:比较是否为同一个对象。

NoneTrueFalse 等单例判断外,普通值比较通常使用 ==

7.6 赋值表达式

现代 Python 支持海象运算符 :=

python 复制代码
if (length := len("Python")) > 5:
    print(f"字符串长度为 {length}")

它可以在表达式中完成赋值,但不应为了减少一行代码而过度使用。


8. 条件判断与循环

8.1 if 条件判断

python 复制代码
score = 85

if score >= 90:
    level = "优秀"
elif score >= 80:
    level = "良好"
elif score >= 60:
    level = "及格"
else:
    level = "不及格"

print(level)

8.2 三元表达式

python 复制代码
age = 20
status = "成年" if age >= 18 else "未成年"

print(status)

8.3 match 结构匹配

较新的 Python 3 版本支持 match

python 复制代码
command = "start"

match command:
    case "start":
        print("启动服务")
    case "stop":
        print("停止服务")
    case "restart":
        print("重启服务")
    case _:
        print("未知命令")

match 不只是简单的 switch,还支持结构解构:

python 复制代码
point = (10, 20)

match point:
    case (0, 0):
        print("原点")
    case (x, 0):
        print(f"位于 X 轴:x={x}")
    case (0, y):
        print(f"位于 Y 轴:y={y}")
    case (x, y):
        print(f"普通坐标:x={x}, y={y}")

8.4 for 循环

python 复制代码
names = ["Alice", "Bob", "Charlie"]

for name in names:
    print(name)

配合 range()

python 复制代码
for number in range(1, 6):
    print(number)

输出范围是 15,不包含结束值 6

8.5 enumerate

需要索引时,不要手动维护计数器:

python 复制代码
names = ["Alice", "Bob", "Charlie"]

for index, name in enumerate(names, start=1):
    print(index, name)

8.6 zip

同时遍历多个序列:

python 复制代码
names = ["Alice", "Bob"]
scores = [90, 85]

for name, score in zip(names, scores):
    print(f"{name}: {score}")

默认情况下,zip() 会在最短的序列结束时停止。

8.7 while 循环

python 复制代码
count = 1

while count <= 5:
    print(count)
    count += 1

8.8 break、continue 与 pass

python 复制代码
for number in range(1, 10):
    if number == 3:
        continue

    if number == 8:
        break

    print(number)
  • continue:跳过本次循环剩余代码。
  • break:结束整个循环。
  • pass:什么也不做,作为语法占位符。
python 复制代码
def future_feature():
    pass

8.9 循环中的 else

当循环正常结束、没有被 break 中断时,会执行 else

python 复制代码
numbers = [1, 3, 5, 7]
target = 4

for number in numbers:
    if number == target:
        print("找到了")
        break
else:
    print("没有找到")

9. Python 常用数据结构

9.1 列表 list

列表有序、可变,可以保存重复元素:

python 复制代码
users = ["Alice", "Bob", "Alice"]

常见操作:

python 复制代码
users = ["Alice", "Bob"]

users.append("Charlie")
users.insert(1, "David")
users.remove("Bob")
last_user = users.pop()

print(users)
print(last_user)

切片:

python 复制代码
numbers = [0, 1, 2, 3, 4, 5]

print(numbers[1:4])
print(numbers[:3])
print(numbers[::2])
print(numbers[::-1])

排序:

python 复制代码
numbers = [5, 2, 9, 1]

numbers.sort()
print(numbers)

numbers.sort(reverse=True)
print(numbers)

sorted() 会返回新列表:

python 复制代码
numbers = [5, 2, 9, 1]
new_numbers = sorted(numbers)

print(numbers)
print(new_numbers)

按字段排序:

python 复制代码
users = [
    {"name": "Alice", "age": 20},
    {"name": "Bob", "age": 18},
]

users.sort(key=lambda user: user["age"])
print(users)

9.2 元组 tuple

元组有序,但不能修改:

python 复制代码
point = (10, 20)

元组解包:

python 复制代码
x, y = point

print(x)
print(y)

交换变量:

python 复制代码
a = 10
b = 20

a, b = b, a

只有一个元素的元组必须带逗号:

python 复制代码
value = (1,)

9.3 集合 set

集合无重复元素,适合去重和集合运算:

python 复制代码
numbers = {1, 2, 2, 3}
print(numbers)

输出:

text 复制代码
{1, 2, 3}

常见操作:

python 复制代码
a = {1, 2, 3}
b = {3, 4, 5}

print(a | b)
print(a & b)
print(a - b)
print(a ^ b)

分别表示:

  • 并集
  • 交集
  • 差集
  • 对称差集

集合元素必须是可哈希对象,因此不能直接放入列表:

python 复制代码
# TypeError
values = {[1, 2], [3, 4]}

9.4 字典 dict

字典以键值对保存数据:

python 复制代码
user = {
    "id": 1,
    "name": "Alice",
    "age": 20,
}

访问数据:

python 复制代码
print(user["name"])
print(user.get("email"))
print(user.get("email", "未填写"))

区别如下:

  • user["email"]:键不存在时抛出 KeyError
  • user.get("email"):键不存在时返回 None 或指定默认值。

遍历字典:

python 复制代码
for key, value in user.items():
    print(key, value)

修改和删除:

python 复制代码
user["age"] = 21
user["email"] = "alice@example.com"

removed_age = user.pop("age")

合并字典:

python 复制代码
base_config = {
    "host": "localhost",
    "port": 8000,
}

custom_config = {
    "port": 9000,
    "debug": True,
}

config = base_config | custom_config
print(config)

后面的字典会覆盖相同键。

9.5 如何选择数据结构

数据结构 是否有序 是否可变 是否允许重复 典型场景
list 有序数据集合
tuple 固定结构的数据
set 不依赖位置 去重、集合运算
dict 保留插入顺序 键不重复 键值映射

10. 函数

10.1 定义函数

python 复制代码
def add(a, b):
    return a + b


result = add(10, 20)
print(result)

10.2 默认参数

python 复制代码
def greet(name, message="你好"):
    return f"{message},{name}"


print(greet("Alice"))
print(greet("Bob", "早上好"))

10.3 关键字参数

python 复制代码
def create_user(name, age, enabled=True):
    return {
        "name": name,
        "age": age,
        "enabled": enabled,
    }


user = create_user(age=20, name="Alice")

关键字参数可以提高调用代码的可读性。

10.4 可变位置参数

python 复制代码
def total(*numbers):
    return sum(numbers)


print(total(1, 2, 3, 4))

numbers 在函数内部是一个元组。

10.5 可变关键字参数

python 复制代码
def build_profile(**attributes):
    return attributes


profile = build_profile(name="Alice", age=20, city="Shanghai")
print(profile)

attributes 在函数内部是一个字典。

10.6 参数解包

python 复制代码
def add(a, b):
    return a + b


numbers = [10, 20]
print(add(*numbers))

字典解包:

python 复制代码
def create_user(name, age):
    return {"name": name, "age": age}


data = {
    "name": "Alice",
    "age": 20,
}

user = create_user(**data)

10.7 仅限关键字参数

python 复制代码
def connect(host, *, timeout=10, retry=3):
    print(host, timeout, retry)


connect("localhost", timeout=5, retry=2)

* 后面的参数必须通过关键字传递。

10.8 函数也是对象

函数可以赋值给变量:

python 复制代码
def greet(name):
    return f"你好,{name}"


handler = greet
print(handler("Alice"))

也可以作为参数传递:

python 复制代码
def execute(operation, a, b):
    return operation(a, b)


def multiply(a, b):
    return a * b


print(execute(multiply, 3, 4))

10.9 lambda 表达式

python 复制代码
multiply = lambda a, b: a * b

print(multiply(3, 4))

lambda 适合表达简单的单行函数。逻辑复杂时应使用普通 def

10.10 变量作用域

python 复制代码
name = "全局变量"


def show_name():
    name = "局部变量"
    print(name)


show_name()
print(name)

Python 查找变量时大致遵循 LEGB 规则:

  1. Local:局部作用域
  2. Enclosing:外层函数作用域
  3. Global:模块全局作用域
  4. Built-in:内置作用域

10.11 不要使用可变对象作为默认参数

错误示例:

python 复制代码
def add_item(item, items=[]):
    items.append(item)
    return items

默认参数在函数定义时创建一次,多次调用会共享同一个列表。

正确写法:

python 复制代码
def add_item(item, items=None):
    if items is None:
        items = []

    items.append(item)
    return items

11. 模块与包

11.1 模块

每个 .py 文件都可以作为一个模块。

创建 calculator.py

python 复制代码
def add(a, b):
    return a + b


def subtract(a, b):
    return a - b

在另一个文件中使用:

python 复制代码
import calculator

print(calculator.add(10, 20))

也可以只导入某个函数:

python 复制代码
from calculator import add

print(add(10, 20))

还可以设置别名:

python 复制代码
import calculator as calc

print(calc.add(10, 20))

不要使用通配符导入:

python 复制代码
from calculator import *

因为它会让代码中名称的来源变得不清晰。

11.2 包

包可以理解为用于组织多个模块的目录。

text 复制代码
my_project/
├── main.py
└── app/
    ├── __init__.py
    ├── services.py
    └── utils.py

导入包中的模块:

python 复制代码
from app.services import create_user

虽然现代 Python 支持命名空间包,但初学阶段保留 __init__.py 更直观。

11.3 __name__ 的作用

假设 calculator.py 内容如下:

python 复制代码
def add(a, b):
    return a + b


if __name__ == "__main__":
    print(add(10, 20))

直接运行时:

bash 复制代码
python calculator.py

测试代码会执行。

被其他文件导入时:

python 复制代码
from calculator import add

测试代码不会执行。


12. 面向对象编程

12.1 类和对象

python 复制代码
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f"我叫 {self.name},今年 {self.age} 岁"


user = User("Alice", 20)

print(user.name)
print(user.introduce())

其中:

  • User 是类。
  • user 是对象。
  • __init__ 用于初始化对象。
  • self 表示当前对象。

12.2 实例属性与类属性

python 复制代码
class User:
    species = "Human"

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


alice = User("Alice")
bob = User("Bob")

print(alice.species)
print(bob.species)
  • species 是类属性。
  • name 是实例属性。

12.3 实例方法、类方法和静态方法

python 复制代码
class User:
    count = 0

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

    def introduce(self):
        return f"我是 {self.name}"

    @classmethod
    def get_count(cls):
        return cls.count

    @staticmethod
    def validate_name(name):
        return bool(name and name.strip())

调用:

python 复制代码
user = User("Alice")

print(user.introduce())
print(User.get_count())
print(User.validate_name("Bob"))

12.4 封装与属性控制

Python 没有和部分语言完全相同的强制私有机制。

单下划线表示内部使用约定:

python 复制代码
class Account:
    def __init__(self, balance):
        self._balance = balance

可以使用 property 控制属性访问:

python 复制代码
class Account:
    def __init__(self, balance):
        self._balance = balance

    @property
    def balance(self):
        return self._balance

    @balance.setter
    def balance(self, value):
        if value < 0:
            raise ValueError("余额不能小于 0")

        self._balance = value

使用方式:

python 复制代码
account = Account(100)
account.balance = 200

print(account.balance)

12.5 继承

python 复制代码
class Animal:
    def speak(self):
        raise NotImplementedError


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


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

多态调用:

python 复制代码
animals = [Dog(), Cat()]

for animal in animals:
    print(animal.speak())

12.6 组合优于过度继承

如果一个对象只是"使用"另一个对象,而不是"属于"另一个对象,通常更适合使用组合。

python 复制代码
class EmailSender:
    def send(self, message):
        print(f"发送邮件:{message}")


class UserService:
    def __init__(self, email_sender):
        self.email_sender = email_sender

    def register(self, name):
        print(f"注册用户:{name}")
        self.email_sender.send("注册成功")

组合可以降低类之间的耦合,使测试和替换实现更加容易。

12.7 魔术方法

Python 中以双下划线开头和结尾的方法通常称为特殊方法或魔术方法。

python 复制代码
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def __str__(self):
        return f"{self.name}:{self.price:.2f} 元"

    def __eq__(self, other):
        if not isinstance(other, Product):
            return NotImplemented

        return self.name == other.name and self.price == other.price

使用:

python 复制代码
product = Product("键盘", 299)
print(product)

13. 异常处理

13.1 捕获异常

python 复制代码
try:
    number = int(input("请输入一个整数:"))
    result = 100 / number
    print(result)
except ValueError:
    print("输入内容不是有效整数")
except ZeroDivisionError:
    print("除数不能为 0")

13.2 获取异常信息

python 复制代码
try:
    value = int("abc")
except ValueError as error:
    print(f"转换失败:{error}")

13.3 else 与 finally

python 复制代码
try:
    number = int("10")
except ValueError:
    print("转换失败")
else:
    print(f"转换成功:{number}")
finally:
    print("无论是否出现异常都会执行")
  • else:没有异常时执行。
  • finally:无论是否有异常都会执行。

13.4 主动抛出异常

python 复制代码
def withdraw(balance, amount):
    if amount <= 0:
        raise ValueError("提现金额必须大于 0")

    if amount > balance:
        raise ValueError("余额不足")

    return balance - amount

13.5 自定义异常

python 复制代码
class InsufficientBalanceError(Exception):
    """余额不足异常。"""


def withdraw(balance, amount):
    if amount > balance:
        raise InsufficientBalanceError(
            f"余额不足:余额={balance},提现金额={amount}"
        )

    return balance - amount

13.6 异常处理原则

  1. 只捕获能够处理的异常。
  2. 尽量捕获具体异常类型。
  3. 不要使用空的 except 隐藏错误。
  4. 记录足够的上下文信息。
  5. 不要把正常业务分支全部设计成异常。
  6. 在系统边界统一转换或记录未处理异常。

不推荐:

python 复制代码
try:
    run_task()
except:
    pass

这种写法会隐藏真实错误,包括程序中断信号和系统级异常。


14. 文件与数据读写

14.1 使用 with 打开文件

python 复制代码
with open("example.txt", "w", encoding="utf-8") as file:
    file.write("Hello, Python!\n")

读取文件:

python 复制代码
with open("example.txt", "r", encoding="utf-8") as file:
    content = file.read()

print(content)

with 结束后会自动关闭文件,即使执行过程中发生异常。

14.2 逐行读取

python 复制代码
with open("example.txt", "r", encoding="utf-8") as file:
    for line in file:
        print(line.rstrip())

处理大文件时,逐行读取通常比一次性调用 read() 更节省内存。

14.3 使用 pathlib

python 复制代码
from pathlib import Path

file_path = Path("data") / "users.txt"

file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text("Alice\nBob\n", encoding="utf-8")

content = file_path.read_text(encoding="utf-8")
print(content)

常见操作:

python 复制代码
from pathlib import Path

path = Path("data/users.txt")

print(path.exists())
print(path.name)
print(path.stem)
print(path.suffix)
print(path.parent)
print(path.resolve())

遍历目录:

python 复制代码
from pathlib import Path

for file_path in Path(".").glob("*.py"):
    print(file_path)

递归遍历:

python 复制代码
for file_path in Path(".").rglob("*.py"):
    print(file_path)

14.4 JSON 数据

写入 JSON:

python 复制代码
import json
from pathlib import Path

user = {
    "name": "Alice",
    "age": 20,
    "skills": ["Python", "SQL"],
}

Path("user.json").write_text(
    json.dumps(user, ensure_ascii=False, indent=2),
    encoding="utf-8",
)

读取 JSON:

python 复制代码
import json
from pathlib import Path

content = Path("user.json").read_text(encoding="utf-8")
user = json.loads(content)

print(user["name"])

14.5 CSV 数据

写入 CSV:

python 复制代码
import csv

users = [
    {"name": "Alice", "age": 20},
    {"name": "Bob", "age": 22},
]

with open("users.csv", "w", newline="", encoding="utf-8-sig") as file:
    writer = csv.DictWriter(file, fieldnames=["name", "age"])
    writer.writeheader()
    writer.writerows(users)

读取 CSV:

python 复制代码
import csv

with open("users.csv", "r", newline="", encoding="utf-8-sig") as file:
    reader = csv.DictReader(file)

    for row in reader:
        print(row)

utf-8-sig 在需要使用部分 Windows 表格软件直接打开 CSV 时可能更方便;普通文本文件通常使用 utf-8 即可。


15. 推导式、迭代器与生成器

15.1 列表推导式

普通写法:

python 复制代码
squares = []

for number in range(1, 6):
    squares.append(number ** 2)

列表推导式:

python 复制代码
squares = [number ** 2 for number in range(1, 6)]

带条件:

python 复制代码
even_squares = [
    number ** 2
    for number in range(1, 11)
    if number % 2 == 0
]

推导式适合简单的数据转换。如果嵌套层级太多,应改为普通循环。

15.2 字典推导式

python 复制代码
names = ["Alice", "Bob", "Charlie"]

name_lengths = {
    name: len(name)
    for name in names
}

15.3 集合推导式

python 复制代码
values = [1, 2, 2, 3, 3, 4]
squares = {value ** 2 for value in values}

15.4 可迭代对象与迭代器

列表是可迭代对象:

python 复制代码
numbers = [1, 2, 3]
iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))

继续调用 next() 会抛出 StopIteration

for 循环会在内部自动完成迭代器创建和异常处理。

15.5 生成器

生成器通过 yield 按需产生数据:

python 复制代码
def count_up_to(limit):
    current = 1

    while current <= limit:
        yield current
        current += 1


for number in count_up_to(5):
    print(number)

生成器不会一次性把所有结果放入内存,适合处理:

  • 大文件
  • 大量数据
  • 数据流
  • 分批查询结果
  • 无限序列

生成器表达式:

python 复制代码
squares = (number ** 2 for number in range(1, 1000000))

print(next(squares))
print(next(squares))

注意:生成器通常只能被完整消费一次。


16. 装饰器

装饰器用于在不直接修改原函数主体的情况下,为函数添加额外行为。

16.1 基本装饰器

python 复制代码
from functools import wraps


def log_call(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print(f"开始调用:{function.__name__}")
        result = function(*args, **kwargs)
        print(f"调用结束:{function.__name__}")
        return result

    return wrapper


@log_call
def add(a, b):
    return a + b


print(add(10, 20))

@wraps(function) 可以保留原函数的名称、文档字符串等元数据。

16.2 带参数的装饰器

python 复制代码
from functools import wraps


def retry(max_attempts):
    def decorator(function):
        @wraps(function)
        def wrapper(*args, **kwargs):
            last_error = None

            for attempt in range(1, max_attempts + 1):
                try:
                    return function(*args, **kwargs)
                except RuntimeError as error:
                    last_error = error
                    print(f"第 {attempt} 次执行失败:{error}")

            raise last_error

        return wrapper

    return decorator

使用:

python 复制代码
@retry(max_attempts=3)
def unstable_task():
    raise RuntimeError("服务暂时不可用")

实际项目中的重试还应考虑:

  • 只重试可恢复异常
  • 指数退避
  • 最大等待时间
  • 幂等性
  • 超时控制
  • 日志与监控

17. 类型标注与数据类

17.1 类型标注

python 复制代码
def add(a: int, b: int) -> int:
    return a + b

集合类型:

python 复制代码
def average(values: list[float]) -> float:
    if not values:
        raise ValueError("数据不能为空")

    return sum(values) / len(values)

可为空类型:

python 复制代码
def find_user(user_id: int) -> dict[str, object] | None:
    if user_id == 1:
        return {
            "id": 1,
            "name": "Alice",
        }

    return None

X | None 语法适用于较新的 Python 3 版本;维护旧版本项目时,可以使用 Optional[X]

需要特别注意:类型标注通常不会在运行时自动阻止错误类型传入。它主要供 IDE、静态类型检查器、代码审查和文档工具使用。Python 官方 typing 文档

17.2 类型别名

python 复制代码
UserId = int
UserData = dict[str, object]


def find_user(user_id: UserId) -> UserData | None:
    return None

17.3 dataclass

如果一个类主要用于保存数据,可以使用 dataclass

python 复制代码
from dataclasses import dataclass, field


@dataclass
class User:
    id: int
    name: str
    skills: list[str] = field(default_factory=list)


user = User(
    id=1,
    name="Alice",
    skills=["Python", "SQL"],
)

print(user)

不要直接把可变列表作为默认值。应使用:

python 复制代码
field(default_factory=list)

数据类会自动生成常用方法,例如:

  • __init__
  • __repr__
  • __eq__

18. 虚拟环境与依赖管理

18.1 为什么需要虚拟环境

假设项目 A 依赖某个库的 1.x 版本,项目 B 依赖同一个库的 2.x 版本。如果把所有依赖都安装到全局 Python 环境中,就容易产生版本冲突。

虚拟环境可以让每个项目拥有独立的:

  • Python 执行环境
  • 第三方依赖
  • 命令行工具

虚拟环境通常命名为 .venv,不应该提交到 Git,并且应当能够根据依赖清单重新创建。Python venv 官方文档

18.2 Windows 创建虚拟环境

powershell 复制代码
py -m venv .venv

PowerShell 激活:

powershell 复制代码
.\.venv\Scripts\Activate.ps1

如果由于 PowerShell 执行策略不能运行激活脚本,也可以直接使用虚拟环境中的解释器:

powershell 复制代码
.\.venv\Scripts\python.exe main.py

退出虚拟环境:

powershell 复制代码
deactivate

18.3 macOS 或 Linux 创建虚拟环境

bash 复制代码
python3 -m venv .venv
source .venv/bin/activate

退出:

bash 复制代码
deactivate

18.4 安装第三方包

激活虚拟环境后:

bash 复制代码
python -m pip install requests

推荐使用:

bash 复制代码
python -m pip

而不是直接使用:

bash 复制代码
pip

这样更容易确保 pip 对应的就是当前使用的 Python 解释器。

查看已安装依赖:

bash 复制代码
python -m pip list

查看包信息:

bash 复制代码
python -m pip show requests

卸载:

bash 复制代码
python -m pip uninstall requests

18.5 requirements.txt

导出当前环境中的依赖:

bash 复制代码
python -m pip freeze > requirements.txt

根据依赖文件安装:

bash 复制代码
python -m pip install -r requirements.txt

对于应用项目,应根据团队规范锁定可复现的依赖版本。对于准备发布给其他项目使用的库,则不宜盲目把所有间接依赖都固定成当前环境版本。

18.6 pyproject.toml

现代 Python 项目通常使用 pyproject.toml 保存项目元数据和构建配置。

一个简化示例:

toml 复制代码
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[project]
name = "example-project"
version = "0.1.0"
description = "一个 Python 示例项目"
requires-python = ">=3.10"
dependencies = [
    "requests>=2,<3"
]

安装当前项目:

bash 复制代码
python -m pip install .

开发阶段可以使用可编辑安装:

bash 复制代码
python -m pip install -e .

关于包安装、虚拟环境和依赖文件的完整说明,可以参考 Python Packaging User Guide


19. 常用标准库

19.1 datetime

python 复制代码
from datetime import datetime, timedelta

now = datetime.now()
tomorrow = now + timedelta(days=1)

print(now)
print(tomorrow)
print(now.strftime("%Y-%m-%d %H:%M:%S"))

解析时间:

python 复制代码
text = "2026-08-21 12:30:00"
value = datetime.strptime(text, "%Y-%m-%d %H:%M:%S")

涉及跨时区系统时,应明确时区,不要依赖服务器默认时区。

19.2 collections

统计次数:

python 复制代码
from collections import Counter

words = ["Python", "Java", "Python", "Go"]
counter = Counter(words)

print(counter)
print(counter.most_common(2))

提供默认值的字典:

python 复制代码
from collections import defaultdict

groups = defaultdict(list)

groups["backend"].append("Alice")
groups["backend"].append("Bob")

19.3 itertools

python 复制代码
from itertools import chain

first = [1, 2]
second = [3, 4]

for value in chain(first, second):
    print(value)

19.4 functools

缓存函数结果:

python 复制代码
from functools import lru_cache


@lru_cache(maxsize=128)
def fibonacci(number):
    if number < 2:
        return number

    return fibonacci(number - 1) + fibonacci(number - 2)


print(fibonacci(30))

缓存适用于相同输入必然得到相同输出的函数。不要随意缓存依赖实时外部状态的结果。

19.5 re

python 复制代码
import re

text = "联系电话:13812345678"
match = re.search(r"1\d{10}", text)

if match:
    print(match.group())

复杂文本解析不应全部依赖正则表达式。处理 HTML、JSON、XML 等结构化内容时,应优先使用专用解析器。

19.6 os 与环境变量

python 复制代码
import os

database_url = os.getenv("DATABASE_URL")

if database_url is None:
    raise RuntimeError("缺少 DATABASE_URL 环境变量")

密码、密钥和令牌不应直接写入源代码或提交到 Git。

19.7 argparse

python 复制代码
import argparse

parser = argparse.ArgumentParser(description="用户问候程序")
parser.add_argument("name", help="用户姓名")
parser.add_argument("--age", type=int, help="用户年龄")

args = parser.parse_args()

print(f"你好,{args.name}")

运行:

bash 复制代码
python main.py Alice --age 20

20. 测试、日志与调试

20.1 使用 assert

python 复制代码
def add(a, b):
    return a + b


assert add(1, 2) == 3

assert 适合开发阶段验证内部假设,但不应代替正式的输入校验和业务异常,因为优化模式下断言可能被关闭。

20.2 unittest

业务代码 calculator.py

python 复制代码
def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为 0")

    return a / b

测试代码 test_calculator.py

python 复制代码
import unittest

from calculator import divide


class CalculatorTest(unittest.TestCase):
    def test_divide(self):
        self.assertEqual(5, divide(10, 2))

    def test_divide_by_zero(self):
        with self.assertRaises(ValueError):
            divide(10, 0)


if __name__ == "__main__":
    unittest.main()

运行:

bash 复制代码
python -m unittest

20.3 pytest

pytest 是常用的第三方测试框架。

安装:

bash 复制代码
python -m pip install pytest

示例:

python 复制代码
import pytest

from calculator import divide


def test_divide():
    assert divide(10, 2) == 5


def test_divide_by_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

运行:

bash 复制代码
python -m pytest

20.4 logging

不要在生产项目中全部依赖 print() 输出日志。

python 复制代码
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)

logger = logging.getLogger(__name__)


def create_user(name):
    logger.info("开始创建用户,name=%s", name)

    try:
        if not name:
            raise ValueError("用户名不能为空")

        logger.info("用户创建成功,name=%s", name)
    except ValueError:
        logger.exception("用户创建失败")
        raise

日志中应避免记录:

  • 密码
  • 完整令牌
  • 银行卡信息
  • 身份证完整号码
  • 未脱敏的个人隐私数据

20.5 调试

最简单的断点方式:

python 复制代码
breakpoint()

程序执行到这里时会进入调试器。

常用命令包括:

text 复制代码
n       执行下一行
s       进入函数
c       继续运行
p name  查看变量
q       退出调试

实际开发中还可以使用 IDE 图形化调试器。


21. Python 并发编程

Python 常见并发方式包括:

方式 常见适用场景
threading 阻塞式 I/O、已有同步库
multiprocessing CPU 密集型计算、进程隔离
asyncio 大量并发网络 I/O
任务队列 跨进程、跨机器的后台任务

这只是常见工程判断,不是绝对规则。最终方案还要结合第三方库是否释放解释器锁、任务规模、数据传输成本和部署方式。

21.1 多线程

python 复制代码
from concurrent.futures import ThreadPoolExecutor
from time import sleep


def download(task_id):
    sleep(1)
    return f"任务 {task_id} 完成"


with ThreadPoolExecutor(max_workers=4) as executor:
    results = executor.map(download, range(1, 6))

    for result in results:
        print(result)

21.2 多进程

python 复制代码
from concurrent.futures import ProcessPoolExecutor


def calculate(number):
    return sum(value * value for value in range(number))


if __name__ == "__main__":
    with ProcessPoolExecutor() as executor:
        results = executor.map(
            calculate,
            [1000000, 1200000, 1400000],
        )

        print(list(results))

Windows 使用多进程时,应特别注意:

python 复制代码
if __name__ == "__main__":

21.3 asyncio

python 复制代码
import asyncio


async def fetch(task_id):
    print(f"开始任务:{task_id}")
    await asyncio.sleep(1)
    print(f"完成任务:{task_id}")
    return task_id


async def main():
    results = await asyncio.gather(
        fetch(1),
        fetch(2),
        fetch(3),
    )

    print(results)


if __name__ == "__main__":
    asyncio.run(main())

需要注意:

  • async 不会自动让所有代码变快。
  • 异步函数中执行长时间阻塞操作,会阻塞事件循环。
  • 使用异步框架时,应选择异步数据库和异步 HTTP 客户端。
  • CPU 密集型计算通常不应直接运行在事件循环中。

22. Python 项目结构

一个中小型项目可以采用以下结构:

text 复制代码
example_project/
├── pyproject.toml
├── README.md
├── .gitignore
├── src/
│   └── example_project/
│       ├── __init__.py
│       ├── main.py
│       ├── models.py
│       ├── services.py
│       └── repositories.py
└── tests/
    ├── __init__.py
    └── test_services.py

各目录职责:

  • src/:业务源代码。
  • tests/:测试代码。
  • pyproject.toml:项目和构建配置。
  • README.md:项目说明。
  • .gitignore:不需要提交的文件。

常见 .gitignore

gitignore 复制代码
__pycache__/
*.py[cod]
.venv/
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
htmlcov/
build/
dist/
*.egg-info/
.env

不要提交:

  • 虚拟环境
  • 缓存文件
  • 本地密钥
  • 数据库密码
  • API Token
  • IDE 临时文件
  • 构建产物

22.1 分层建议

对于业务项目,可以按照职责拆分:

text 复制代码
接口层
  ↓
服务层
  ↓
数据访问层
  ↓
数据库或外部服务

例如:

python 复制代码
class UserRepository:
    def find_by_id(self, user_id):
        return {
            "id": user_id,
            "name": "Alice",
        }


class UserService:
    def __init__(self, repository):
        self.repository = repository

    def get_user(self, user_id):
        if user_id <= 0:
            raise ValueError("用户 ID 必须大于 0")

        return self.repository.find_by_id(user_id)

清晰的职责边界通常比"文件越多越专业"更重要。小项目不需要过早设计复杂架构。


23. 综合实战:命令行待办事项程序

下面使用标准库实现一个简单的待办事项程序,支持:

  • 添加任务
  • 查看任务
  • 完成任务
  • 删除任务
  • 使用 JSON 保存数据

创建 todo.py

python 复制代码
import argparse
import json
from pathlib import Path


DATA_FILE = Path("tasks.json")


def load_tasks():
    if not DATA_FILE.exists():
        return []

    try:
        content = DATA_FILE.read_text(encoding="utf-8")
        data = json.loads(content)
    except json.JSONDecodeError as error:
        raise RuntimeError(
            f"任务文件格式错误:{DATA_FILE}"
        ) from error

    if not isinstance(data, list):
        raise RuntimeError("任务文件的顶层数据必须是列表")

    return data


def save_tasks(tasks):
    content = json.dumps(
        tasks,
        ensure_ascii=False,
        indent=2,
    )

    DATA_FILE.write_text(content, encoding="utf-8")


def add_task(title):
    title = title.strip()

    if not title:
        raise ValueError("任务标题不能为空")

    tasks = load_tasks()

    next_id = max(
        (task["id"] for task in tasks),
        default=0,
    ) + 1

    task = {
        "id": next_id,
        "title": title,
        "completed": False,
    }

    tasks.append(task)
    save_tasks(tasks)

    print(f"任务添加成功:[{next_id}] {title}")


def list_tasks():
    tasks = load_tasks()

    if not tasks:
        print("暂无任务")
        return

    for task in tasks:
        status = "√" if task["completed"] else " "
        print(f"[{status}] {task['id']}: {task['title']}")


def complete_task(task_id):
    tasks = load_tasks()

    for task in tasks:
        if task["id"] == task_id:
            task["completed"] = True
            save_tasks(tasks)
            print(f"任务已完成:{task_id}")
            return

    raise ValueError(f"任务不存在:{task_id}")


def delete_task(task_id):
    tasks = load_tasks()

    remaining_tasks = [
        task
        for task in tasks
        if task["id"] != task_id
    ]

    if len(remaining_tasks) == len(tasks):
        raise ValueError(f"任务不存在:{task_id}")

    save_tasks(remaining_tasks)
    print(f"任务已删除:{task_id}")


def create_parser():
    parser = argparse.ArgumentParser(
        description="命令行待办事项程序"
    )

    subparsers = parser.add_subparsers(
        dest="command",
        required=True,
    )

    add_parser = subparsers.add_parser(
        "add",
        help="添加任务",
    )
    add_parser.add_argument("title", help="任务标题")

    subparsers.add_parser(
        "list",
        help="查看任务",
    )

    complete_parser = subparsers.add_parser(
        "complete",
        help="完成任务",
    )
    complete_parser.add_argument(
        "task_id",
        type=int,
        help="任务 ID",
    )

    delete_parser = subparsers.add_parser(
        "delete",
        help="删除任务",
    )
    delete_parser.add_argument(
        "task_id",
        type=int,
        help="任务 ID",
    )

    return parser


def main():
    parser = create_parser()
    args = parser.parse_args()

    try:
        if args.command == "add":
            add_task(args.title)
        elif args.command == "list":
            list_tasks()
        elif args.command == "complete":
            complete_task(args.task_id)
        elif args.command == "delete":
            delete_task(args.task_id)
    except (ValueError, RuntimeError) as error:
        parser.error(str(error))


if __name__ == "__main__":
    main()

添加任务:

bash 复制代码
python todo.py add "学习 Python"
python todo.py add "编写一个命令行程序"

查看任务:

bash 复制代码
python todo.py list

完成任务:

bash 复制代码
python todo.py complete 1

删除任务:

bash 复制代码
python todo.py delete 2

这个程序虽然简单,但已经包含了不少实际开发知识:

  • 函数拆分
  • 命令行参数
  • JSON 序列化
  • 文件读写
  • 输入校验
  • 异常处理
  • 列表推导式
  • 程序入口

后续可以继续扩展:

  1. 增加任务创建时间。
  2. 增加任务优先级。
  3. 增加任务截止日期。
  4. 使用 SQLite 保存数据。
  5. 为每个函数编写测试。
  6. 把程序打包成可安装的命令行工具。
  7. 使用 FastAPI 提供 Web API。
  8. 增加 Web 或桌面图形界面。

24. 常见问题与易错点

24.1 is== 混用

错误:

python 复制代码
if value is 100:
    print("等于 100")

正确:

python 复制代码
if value == 100:
    print("等于 100")

判断 None 时使用:

python 复制代码
if value is None:
    print("没有值")

24.2 修改正在遍历的列表

不推荐:

python 复制代码
numbers = [1, 2, 3, 4]

for number in numbers:
    if number % 2 == 0:
        numbers.remove(number)

推荐创建新列表:

python 复制代码
numbers = [
    number
    for number in numbers
    if number % 2 != 0
]

24.3 列表引用共享

python 复制代码
a = [1, 2, 3]
b = a

b.append(4)

print(a)

输出:

text 复制代码
[1, 2, 3, 4]

因为 ab 引用了同一个列表。

创建浅拷贝:

python 复制代码
b = a.copy()

嵌套对象需要根据实际情况考虑深拷贝:

python 复制代码
from copy import deepcopy

b = deepcopy(a)

深拷贝不是默认最佳方案。很多时候,重新设计数据流或使用不可变对象更清晰。

24.4 二维列表初始化错误

错误:

python 复制代码
matrix = [[0] * 3] * 3
matrix[0][0] = 1

print(matrix)

三行引用了同一个内部列表。

正确:

python 复制代码
matrix = [
    [0] * 3
    for _ in range(3)
]

24.5 浮点数不能直接用于精确金额判断

不推荐:

python 复制代码
total = 0.1 + 0.2

if total == 0.3:
    print("相等")

可以使用误差比较:

python 复制代码
import math

print(math.isclose(0.1 + 0.2, 0.3))

金额计算可根据业务精度要求使用 Decimal

24.6 捕获过于宽泛的异常

不推荐:

python 复制代码
try:
    process()
except Exception:
    print("执行失败")

如果确实需要在程序最外层统一捕获,应记录完整异常堆栈:

python 复制代码
import logging

logger = logging.getLogger(__name__)

try:
    process()
except Exception:
    logger.exception("程序执行失败")
    raise

24.7 在全局环境安装所有依赖

不推荐直接把不同项目依赖全部安装到系统 Python。

每个项目应该创建独立虚拟环境:

bash 复制代码
python -m venv .venv

24.8 使用字符串拼接文件路径

不推荐:

python 复制代码
file_path = directory + "/" + file_name

推荐:

python 复制代码
from pathlib import Path

file_path = Path(directory) / file_name

24.9 把密钥写在代码中

错误:

python 复制代码
API_KEY = "真实密钥"

更合理的方式是从环境变量读取:

python 复制代码
import os

api_key = os.getenv("API_KEY")

if not api_key:
    raise RuntimeError("缺少 API_KEY")

24.10 过早优化

优化代码前应先确认真正的性能瓶颈。

可以使用:

bash 复制代码
python -m cProfile main.py

基本原则:

  1. 先保证代码正确。
  2. 再编写测试。
  3. 使用数据定位瓶颈。
  4. 优化最耗时的部分。
  5. 优化后重新验证正确性和性能。

25. Python 学习路线

25.1 第一阶段:语言基础

学习内容:

  • 变量和数据类型
  • 字符串
  • 列表、元组、集合、字典
  • 条件判断
  • 循环
  • 函数
  • 文件读写
  • 异常处理

练习项目:

  • 猜数字游戏
  • 通讯录
  • 文本词频统计
  • 文件批量重命名
  • 命令行记账程序

25.2 第二阶段:编程能力

学习内容:

  • 模块和包
  • 面向对象
  • 迭代器和生成器
  • 装饰器
  • 类型标注
  • 标准库
  • 单元测试
  • 日志
  • Git

练习项目:

  • 待办事项程序
  • 日志分析器
  • CSV 数据处理器
  • API 数据同步工具
  • 简单爬虫

25.3 第三阶段:工程化

学习内容:

  • 虚拟环境
  • 依赖管理
  • pyproject.toml
  • 项目分层
  • 配置管理
  • 测试覆盖
  • 静态检查
  • 自动格式化
  • CI/CD
  • Docker

常见工程工具:

  • pytest
  • ruff
  • mypy
  • black
  • pre-commit

工具不是越多越好。应先建立代码规范、测试策略和明确的交付要求,再选择合适的工具。

25.4 第四阶段:选择方向

Web 开发

建议学习:

  • HTTP
  • FastAPI、Flask 或 Django
  • SQL
  • PostgreSQL 或 MySQL
  • Redis
  • 身份认证
  • Docker
  • API 设计
数据分析

建议学习:

  • NumPy
  • Pandas 或 Polars
  • Matplotlib
  • Jupyter
  • SQL
  • 统计学基础
人工智能

建议学习:

  • NumPy
  • Pandas
  • 线性代数
  • 概率统计
  • Scikit-learn
  • PyTorch
  • 模型评估
  • 数据处理
自动化测试

建议学习:

  • Pytest
  • Requests
  • Playwright
  • 接口测试
  • Mock
  • 测试报告
  • CI/CD
运维与自动化

建议学习:

  • Linux
  • Shell
  • 网络基础
  • 日志处理
  • Docker
  • Kubernetes
  • 云平台 SDK
  • 监控与告警

26. 总结

Python 的核心优势是语法简洁、开发效率高、标准库丰富、第三方生态完善。它既可以作为学习编程的第一门语言,也能够承担真实的生产项目。

学习 Python 时,不应只停留在记忆语法。更有效的学习方式是:

  1. 理解变量、对象和引用关系。
  2. 熟练使用列表、字典、集合和元组。
  3. 学会通过函数拆分复杂逻辑。
  4. 理解异常、文件和模块边界。
  5. 为每个项目创建独立虚拟环境。
  6. 使用测试验证关键逻辑。
  7. 使用日志记录运行过程。
  8. 从小型项目开始积累工程经验。
  9. 根据实际方向学习 Web、数据、AI 或自动化生态。
  10. 保持代码简单、明确、可验证。

Python 入门并不困难,真正需要长期积累的是程序设计、问题拆解、测试意识和工程实践。掌握基础语法后,应尽快完成几个能够独立运行的小项目,在不断编写、调试和改进代码的过程中形成自己的知识体系。


参考资料

相关推荐
艾伦_耶格宇2 小时前
【AI】-4 OpenCode Go 接入 Obsidian 完整指南
运维·开发语言·人工智能·agent·opencode
旋生万物3 小时前
【终极实战】用Python从零“生成“一个宇宙:螺旋干涉模型的代码实现
开发语言·前端·人工智能·react.js·php·wpf
Niuguangshuo3 小时前
DeepFilterNet 3:端侧实时全带降噪的开源标杆
python
第一程序员3 小时前
AI 辅助编程的 7 个误区:把模型当高级搜索引擎是对它的最大浪费
python·rust·github
16月6日-晴3 小时前
Java面向对象进阶—多态
java·开发语言
冯汉栩4 小时前
Swift Control RollingCountdownView(动画倒计时)
开发语言·ios·swift
lisanmengmeng4 小时前
搭建elk环境并接入frostmourne,实现监控报警效果(五)
开发语言·elk·日志·日志监控
Groundwork Explorer4 小时前
W5500 网卡编程初始化与使用指南
python·单片机
oh,huoyuyan4 小时前
JS 动态网页抓不到?试试火车采集器网页抓取工具
开发语言·javascript·ecmascript