跳到主要内容

模块与包

模块(Module)和包(Package)是 Python 组织代码的重要方式,它们帮助我们更好地管理和复用代码。

模块基础

什么是模块

模块 是一个包含 Python 定义和语句的文件,文件名就是模块名加上 .py 后缀。模块可以包含函数、类、变量和可执行代码。

# my_module.py
"""这是我的模块"""

# 模块变量
module_var = "我是模块变量"

# 模块函数
def greet(name):
return f"Hello, {name}!"

# 模块类
class Person:
def __init__(self, name):
self.name = name

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

# 模块执行代码
if __name__ == "__main__":
print("模块被直接运行")
else:
print("模块被导入")

导入模块

使用 import 语句导入模块:

# 导入整个模块
import my_module

# 使用模块中的内容
print(my_module.module_var)
print(my_module.greet("Alice"))

person = my_module.Person("Bob")
print(person.say_hello())

import 语句

基本导入

# 导入单个模块
import math

# 使用模块功能
print(math.pi) # 3.14159...
print(math.sqrt(16)) # 4.0

# 导入多个模块
import math, random, sys

# 但推荐分行导入(PEP 8)
import math
import random
import sys

导入模块并创建别名

# 使用 as 关键字创建别名
import math as m

print(m.pi) # 3.14159...
print(m.sqrt(25)) # 5.0

# 常见用途
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

模块名称修饰

导入模块后,模块名会被添加到当前符号表中:

import math

# 查看已导入的模块
print(dir()) # 包含 'math'

# 查看模块内容
print(dir(math)) # 显示 math 模块的所有属性和方法

# 查看模块文档
print(math.__doc__)
print(math.__name__) # 'math'
print(math.__file__) # 模块文件路径

from...import

导入特定属性

# 从模块中导入特定函数或变量
from math import pi, sqrt

# 直接使用,不需要模块前缀
print(pi) # 3.14159...
print(sqrt(16)) # 4.0

# 但不能访问未导入的内容
# print(math.sin(1)) # NameError: name 'math' is not defined

导入所有内容

# 导入模块的所有内容(不推荐)
from math import *

# 可以直接使用所有内容
print(pi)
print(sin(1))
print(cos(1))

# 问题:可能污染命名空间,造成命名冲突

为什么不推荐使用 from module import *

# module1.py
def func():
return "模块1的函数"

# module2.py
def func():
return "模块2的函数"

# main.py
from module1 import *
from module2 import * # 覆盖了 module1 的 func

print(func()) # "模块2的函数"(module1 的 func 被覆盖)

导入并重命名

from math import sqrt as square_root

print(square_root(16)) # 4.0

导入时机

Python 模块只在第一次被导入时执行,后续导入会使用缓存的模块对象:

# my_module.py
print("模块被加载")

count = 0

def increment():
global count
count += 1
return count

# main.py
import my_module # 输出: 模块被加载
print(my_module.increment()) # 1

import my_module # 不会再次输出(使用缓存)
print(my_module.increment()) # 2

模块搜索路径

Python 按照以下顺序搜索模块:

import sys

# 查看模块搜索路径
print(sys.path)
# [
# '', # 当前目录
# 'PYTHONPATH环境变量',
# '标准库目录',
# 'site-packages目录'
# ]

临时添加搜索路径

import sys

# 添加自定义路径
sys.path.append('/path/to/modules')

# 现在可以导入该路径下的模块
import my_module

标准库

Python 自带丰富的标准库,无需安装即可使用。

常用标准库模块

os - 操作系统接口

import os

# 获取当前工作目录
print(os.getcwd()) # /Users/username/project

# 改变工作目录
os.chdir('/path/to/directory')

# 列出目录内容
print(os.listdir('.'))

# 创建目录
os.mkdir('new_dir') # 创建单级目录
os.makedirs('dir1/dir2', exist_ok=True) # 创建多级目录

# 删除目录
os.rmdir('new_dir') # 删除空目录
os.removedirs('dir1/dir2') # 删除多级空目录

# 删除文件
os.remove('file.txt')

# 文件路径操作
print(os.path.exists('file.txt')) # 检查文件是否存在
print(os.path.isfile('file.txt')) # 是否是文件
print(os.path.isdir('dir')) # 是否是目录
print(os.path.getsize('file.txt')) # 获取文件大小

# 路径拼接(跨平台)
path = os.path.join('dir', 'subdir', 'file.txt')
print(path) # dir/subdir/file.txt (Unix) 或 dir\subdir\file.txt (Windows)

# 分离路径和文件名
dirname, filename = os.path.split('/path/to/file.txt')
print(dirname) # /path/to
print(filename) # file.txt

# 分离文件名和扩展名
name, ext = os.path.splitext('file.txt')
print(name) # file
print(ext) # .txt

# 环境变量
print(os.environ.get('HOME'))
print(os.environ.get('PATH'))

sys - 系统相关

import sys

# Python 版本
print(sys.version) # Python 解释器版本
print(sys.version_info) # 版本信息元组

# 命令行参数
print(sys.argv) # ['script.py', 'arg1', 'arg2']
if len(sys.argv) > 1:
print(f"第一个参数: {sys.argv[1]}")

# 退出程序
sys.exit(0) # 正常退出
sys.exit(1) # 异常退出

# 递归深度限制
print(sys.getrecursionlimit()) # 1000
sys.setrecursionlimit(2000)

# 标准输入输出
sys.stdout.write("Hello\n")
sys.stderr.write("Error\n")

# 获取平台信息
print(sys.platform) # win32, linux, darwin
print(sys.maxsize) # 最大整数

# 模块搜索路径
print(sys.path)

datetime - 日期时间

from datetime import date, time, datetime, timedelta

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

print(today) # 2025-02-03
print(now) # 2025-02-03 15:30:45.123456

# 创建日期和时间
d = date(2025, 2, 3)
t = time(15, 30, 45)
dt = datetime(2025, 2, 3, 15, 30, 45)

# 日期格式化
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2025-02-03 15:30:45
print(now.strftime("%Y年%m月%d日")) # 2025年02月03日

# 字符串转日期
dt_str = "2025-02-03 15:30:45"
dt_parsed = datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")

# 日期运算
delta = timedelta(days=7, hours=3)

tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
yesterday = today - timedelta(days=1)

print(tomorrow) # 2025-02-04
print(next_week) # 2025-02-10
print(yesterday) # 2025-02-02

# 计算日期差
date1 = date(2025, 1, 1)
date2 = date(2025, 2, 3)
diff = date2 - date1
print(diff.days) # 33

# 访问日期组件
print(now.year) # 2025
print(now.month) # 2
print(now.day) # 3
print(now.hour) # 15
print(now.minute) # 30
print(now.second) # 45

random - 随机数

import random

# 随机整数
print(random.randint(1, 10)) # 1-10 之间的随机整数(包含两端)
print(random.randrange(1, 10)) # 1-9 之间的随机整数
print(random.randrange(0, 100, 5)) # 0-95 之间,步长为5

# 随机浮点数
print(random.random()) # 0.0-1.0 之间的随机浮点数
print(random.uniform(1.0, 10.0)) # 1.0-10.0 之间的随机浮点数

# 从序列中随机选择
items = ['apple', 'banana', 'orange', 'grape']
print(random.choice(items)) # 随机选择一个元素
print(random.sample(items, 2)) # 随机选择2个不重复的元素
print(random.choices(items, k=3)) # 随机选择3个元素(可重复)

# 打乱序列
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers) # [3, 1, 5, 2, 4](随机顺序)

# 生成随机密码
import string
chars = string.ascii_letters + string.digits + string.punctuation
password = ''.join(random.choices(chars, k=12))
print(password) # 随机12位密码

# 设置随机种子(可复现)
random.seed(42)
print(random.random()) # 0.6394267984578837
print(random.random()) # 0.025010755222666936

random.seed(42) # 重置种子
print(random.random()) # 0.6394267984578837(与之前相同)

json - JSON 数据处理

import json

# Python 对象转 JSON 字符串(序列化)
data = {
"name": "Alice",
"age": 25,
"is_student": True,
"courses": ["Math", "Science"],
"address": {
"city": "New York",
"zip": "10001"
}
}

json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)
# {
# "name": "Alice",
# "age": 25,
# "is_student": true,
# "courses": ["Math", "Science"],
# "address": {
# "city": "New York",
# "zip": "10001"
# }
# }

# JSON 字符串转 Python 对象(反序列化)
parsed_data = json.loads(json_str)
print(parsed_data["name"]) # Alice

# 读写 JSON 文件
# 写入 JSON 文件
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)

# 读取 JSON 文件
with open('data.json', 'r', encoding='utf-8') as f:
loaded_data = json.load(f)

print(loaded_data)

pathlib - 面向对象的路径操作(推荐)

from pathlib import Path

# 创建路径对象
current_dir = Path('.')
home_dir = Path.home()
file_path = Path('docs/python/test.py')

# 路径拼接
new_path = Path('docs') / 'python' / 'test.py'

# 获取路径信息
print(file_path.exists()) # 是否存在
print(file_path.is_file()) # 是否是文件
print(file_path.is_dir()) # 是否是目录
print(file_path.name) # 文件名
print(file_path.stem) # 文件名(不含扩展名)
print(file_path.suffix) # 扩展名
print(file_path.parent) # 父目录

# 读写文件
content = file_path.read_text(encoding='utf-8')
file_path.write_text('Hello, World!', encoding='utf-8')

# 创建目录
Path('new_dir').mkdir(exist_ok=True)
Path('dir1/dir2').mkdir(parents=True, exist_ok=True)

# 遍历目录
for file in Path('.').iterdir():
print(file)

# 查找文件
python_files = list(Path('.').glob('*.py'))
all_files = list(Path('.').rglob('*.*'))

# 复制、移动、删除
file_path.rename('new_name.py') # 重命名
file_path.unlink() # 删除文件

collections - 高级数据结构

from collections import Counter, defaultdict, OrderedDict, namedtuple

# Counter - 计数器
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
word_count = Counter(words)
print(word_count) # Counter({'apple': 3, 'banana': 2, 'orange': 1})

print(word_count.most_common(2)) # [('apple', 3), ('banana', 2)]

# defaultdict - 默认值字典
dd = defaultdict(int)
dd['apple'] += 1 # 不需要先检查键是否存在
print(dd['apple']) # 1

dd_list = defaultdict(list)
dd_list['fruits'].append('apple')
dd_list['fruits'].append('banana')
print(dd_list['fruits']) # ['apple', 'banana']

# namedtuple - 命名元组
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x) # 10
print(p.y) # 20
print(p[0]) # 10(像普通元组一样访问)

更多标准库模块

# re - 正则表达式
import re
pattern = r'\d+'
result = re.findall(pattern, 'There are 123 apples and 456 oranges')
print(result) # ['123', '456']

# hashlib - 哈希算法
import hashlib
md5_hash = hashlib.md5(b'Hello, World!')
print(md5_hash.hexdigest()) # ed076287532e86365e841e92bfc50d8c

# urllib - URL 处理
from urllib.parse import urlparse, parse_qs
url = 'https://example.com/search?q=python&lang=en'
parsed = urlparse(url)
print(parsed.scheme) # https
print(parsed.netloc) # example.com
print(parsed.path) # /search

# time - 时间相关
import time
print(time.time()) # Unix 时间戳
time.sleep(2) # 暂停2秒

# uuid - 唯一标识符
import uuid
print(uuid.uuid4()) # 随机 UUID
print(uuid.uuid1()) # 基于时间和主机的 UUID

第三方库

第三方库需要通过包管理器安装后才能使用。

pip 使用

pip 是 Python 的包管理工具,用于安装和管理第三方库。

常用命令

# 查看 pip 版本
pip --version

# 升级 pip
pip install --upgrade pip

# 搜索包
pip search package_name

# 安装包
pip install package_name

# 安装指定版本
pip install package_name==1.0.0
pip install "package_name>=1.0.0,<2.0.0"

# 安装最新版本
pip install --upgrade package_name

# 卸载包
pip uninstall package_name

# 查看已安装的包
pip list

# 查看包的详细信息
pip show package_name

# 查看过期的包
pip list --outdated

# 导出依赖列表
pip freeze > requirements.txt

# 从依赖列表安装
pip install -r requirements.txt

# 国内镜像源安装(加速)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package_name

# 配置永久镜像源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

常见第三方库

# Web 开发
pip install django flask fastapi

# 数据科学
pip install numpy pandas matplotlib

# 机器学习
pip install scikit-learn tensorflow pytorch

# 爬虫
pip install requests beautifulsoup4 scrapy

# 数据库
pip install sqlalchemy pymongo pymysql

# 测试
pip install pytest unittest

# 其他实用库
pip install python-dotenv # 环境变量管理
pip install click # 命令行工具
pip install rich # 终端美化

requirements.txt

requirements.txt 文件用于记录项目的所有依赖及其版本。

创建 requirements.txt

# 方式一:手动创建
# requirements.txt
flask==2.3.0
requests>=2.28.0
pandas>=1.5.0,<2.0.0
numpy~=1.24.0 # 等同于 >=1.24.0,<1.25.0

# 方式二:自动生成
pip freeze > requirements.txt

使用 requirements.txt

# 安装所有依赖
pip install -r requirements.txt

# requirements.txt 示例
# Web 框架
Flask==2.3.0
Werkzeug==2.3.0

# 数据处理
pandas==2.0.0
numpy==1.24.0

# 工具库
python-dotenv==1.0.0
requests==2.31.0

# 开发依赖(可选)
pytest==7.4.0
black==23.7.0

版本说明符

# 版本指定方式
package==1.0.0 # 精确匹配 1.0.0
package>=1.0.0 # 大于等于 1.0.0
package<2.0.0 # 小于 2.0.0
package>=1.0.0,<2.0.0 # 1.0.0 <= version < 2.0.0
package~=1.2.3 # 兼容版本:>=1.2.3,<1.3.0
package~=1.2 # 兼容版本:>=1.2,<2.0
package!=1.0.0 # 不等于 1.0.0

虚拟环境

虚拟环境可以为每个项目创建独立的 Python 环境,避免不同项目之间的包版本冲突。

venv(Python 3.3+ 内置)

# 创建虚拟环境
python -m venv myenv
python -m venv --clear myenv # 清除并重新创建
python -m venv --system-site-packages myenv # 包含系统包

# 激活虚拟环境

# Windows
myenv\Scripts\activate

# macOS/Linux
source myenv/bin/activate

# 退出虚拟环境
deactivate

# 激活后,命令行提示符会显示环境名
(myenv) $

# 在虚拟环境中安装包
pip install package_name

# 查看虚拟环境中的包
pip list

# 导出依赖
pip freeze > requirements.txt

# 删除虚拟环境(直接删除目录)
# Windows
rmdir /s myenv

# macOS/Linux
rm -rf myenv

virtualenv(第三方工具)

# 安装 virtualenv
pip install virtualenv

# 创建虚拟环境
virtualenv myenv
virtualenv -p python3.10 myenv # 指定 Python 版本

# 激活和退出与 venv 相同

pipenv(现代替代方案)

# 安装 pipenv
pip install pipenv

# 创建虚拟环境并安装依赖
cd myproject
pipenv install # 创建虚拟环境
pipenv install requests # 安装包并自动添加到 Pipfile

# 激活虚拟环境
pipenv shell

# 在虚拟环境中运行命令
pipenv run python script.py

# 安装开发依赖
pipenv install pytest --dev

# 导出 requirements.txt
pipenv requirements > requirements.txt

# 退出虚拟环境
exit

最佳实践

# 项目结构
myproject/
├── .git/
├── .gitignore
├── venv/ # 虚拟环境(添加到 .gitignore)
├── requirements.txt # 依赖列表
├── Pipfile # pipenv 依赖文件(可选)
├── src/
└── tests/

# .gitignore 内容
venv/
env/
.venv/
*.pyc
__pycache__/
.env

包的结构

包是包含多个模块的目录,用于组织大型项目。

包的基本结构

my_package/
├── __init__.py # 包标识文件(可以为空)
├── module1.py # 模块1
├── module2.py # 模块2
├── subpackage/ # 子包
│ ├── __init__.py
│ ├── module3.py
│ └── module4.py
└── utils/ # 子包
├── __init__.py
└── helpers.py

创建和使用包

创建包

# my_package/__init__.py
"""这是我的包"""

__version__ = "1.0.0"
__author__ = "Your Name"

# 导入常用功能到包级别
from .module1 import func1
from .module2 import MyClass

# my_package/module1.py
"""模块1"""

def func1():
return "这是模块1的函数"

def helper():
return "模块1的辅助函数"

# my_package/module2.py
"""模块2"""

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

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

使用包

# 导入整个包
import my_package

# 使用包中的内容
print(my_package.__version__)
print(my_package.func1())

obj = my_package.MyClass("Alice")
print(obj.greet())

# 导入包的模块
from my_package import module1, module2

print(module1.func1())
obj = module2.MyClass("Bob")

# 直接导入包中的内容
from my_package.module1 import func1, helper

print(func1())
print(helper())

# 导入子包
from my_package.subpackage import module3
from my_package.utils.helpers import some_function

包的相对导入

在包内部使用相对导入:

# my_package/module1.py
from . import module2 # 导入同级模块
from .subpackage import module3 # 导入子包
from .. import parent_module # 导入父级模块(不推荐)

# my_package/subpackage/module3.py
from .. import module1 # 导入父包的模块
from ..module2 import MyClass # 导入父包的类

包的 init.py

__init__.py 文件标识一个目录为 Python 包,可以包含初始化代码。

空的 init.py

# my_package/__init__.py
# 空文件,仅标识为包
pass

包含初始化代码

# my_package/__init__.py
"""包的初始化文件"""

__version__ = "1.0.0"
__all__ = ['func1', 'MyClass', 'helper'] # 定义 from package import * 时导入的内容

# 初始化代码
print("包被导入")

# 导入常用功能
from .module1 import func1, helper
from .module2 import MyClass

# 定义包级别的变量
config = {
"debug": True,
"timeout": 30
}

使用 all 控制导入

# my_package/__init__.py
__all__ = ['func1', 'MyClass']

# 导入时会应用 __all__ 的限制
from my_package import * # 只导入 func1 和 MyClass

包的发布

将包发布到 PyPI,让其他人可以使用。

项目结构

my_project/
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── module1.py
│ └── module2.py
├── tests/
│ └── test_module.py
├── README.md
├── LICENSE
├── pyproject.toml # 现代 Python 项目配置
├── setup.py # 传统配置(可选)
└── .gitignore

pyproject.toml 配置

# pyproject.toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my-package"
version = "1.0.0"
description = "我的 Python 包"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "your.email@example.com"}
]
keywords = ["package", "example"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]

dependencies = [
"requests>=2.28.0",
]

[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"flake8>=6.0.0",
]
docs = [
"sphinx>=5.0.0",
"sphinx-rtd-theme>=1.0.0",
]

[project.urls]
Homepage = "https://github.com/username/my-package"
Documentation = "https://my-package.readthedocs.io"
Repository = "https://github.com/username/my-package"
Issues = "https://github.com/username/my-package/issues"

[tool.setuptools]
packages = ["my_package"]

[tool.setuptools.package-data]
my_package = ["*.txt", "*.json"]

README.md

# My Package

这是我的 Python 包的简短描述。

## 安装

```bash
pip install my-package

使用

import my_package

my_package.func1()

开发

# 克隆仓库
git clone https://github.com/username/my-package.git
cd my-package

# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate

# 安装开发依赖
pip install -e ".[dev]"

# 运行测试
pytest

许可证

MIT License


### 构建和发布

```bash
# 安装构建工具
pip install build twine

# 构建包
python -m build

# 检查包
twine check dist/*

# 发布到 PyPI(生产环境)
twine upload dist/*

# 发布到 TestPyPI(测试环境)
twine upload --repository testpypi dist/*

# 从 TestPyPI 安装测试
pip install --index-url https://test.pypi.org/simple/ my-package

版本管理

# 使用版本号(遵循语义化版本)
# 1.0.0 -> 1.0.1 -> 1.1.0 -> 2.0.0
# 格式: MAJOR.MINOR.PATCH
# MAJOR: 不兼容的 API 变更
# MINOR: 向下兼容的功能新增
# PATCH: 向下兼容的问题修复

模块与包的最佳实践

1. 组织结构

# 推荐的项目结构
project/
├── src/
│ └── mypackage/ # 主要代码
│ ├── __init__.py
│ ├── core.py # 核心功能
│ ├── utils.py # 工具函数
│ └── config.py # 配置
├── tests/ # 测试代码
│ ├── __init__.py
│ ├── test_core.py
│ └── test_utils.py
├── docs/ # 文档
├── examples/ # 示例代码
├── setup.py # 安装配置
├── requirements.txt # 依赖
├── README.md # 说明文档
└── .gitignore

2. 命名规范

# 模块名:小写,下划线分隔
user_profile.py
database_utils.py

# 包名:小写,下划线分隔(短)
my_package/
utils/

# 避免与标准库重名
# 不推荐:random.py, email.py
# 推荐:random_utils.py, email_handler.py

3. 导入顺序

# PEP 8 推荐的导入顺序

# 1. 标准库导入
import os
import sys
from datetime import datetime

# 2. 第三方库导入
import numpy as np
import pandas as pd
from flask import Flask

# 3. 本地应用/库导入
from mypackage import module1
from mypackage.utils import helper_function

# 每组之间用空行分隔

4. 避免循环导入

# 循环导入示例(错误)

# module_a.py
import module_b

def func_a():
module_b.func_b()

# module_b.py
import module_a

def func_b():
module_a.func_a() # 循环依赖

# 解决方案1:延迟导入
# module_a.py
def func_a():
import module_b # 在函数内部导入
module_b.func_b()

# 解决方案2:重构代码
# 将共享功能提取到第三个模块
# module_c.py
def shared_func():
pass

# module_a.py
from module_c import shared_func

5. 使用相对导入

# 在包内部,使用相对导入
# my_package/subpackage/module.py

# 不推荐(绝对导入)
from my_package.utils import helper

# 推荐(相对导入)
from ..utils import helper
from . import sibling_module

6. 文档和注释

# my_package/utils.py
"""工具函数模块

这个模块包含各种工具函数。
"""

def helper_function(param1, param2):
"""执行某个操作。

Args:
param1: 参数1的说明
param2: 参数2的说明

Returns:
返回值的说明

Raises:
ValueError: 当参数无效时
"""
if not param1:
raise ValueError("param1 不能为空")

return param1 + param2

7. 使用 name == "main"

# my_module.py
"""模块文档"""

def main():
"""主函数"""
print("模块被直接运行")
# 执行某些操作

def helper():
"""辅助函数"""
pass

# 只在直接运行时执行,导入时不执行
if __name__ == "__main__":
main()

8. 使用类型提示

# my_package/types.py
from typing import List, Dict, Optional

def process_data(items: List[int]) -> Dict[str, int]:
"""处理数据列表

Args:
items: 整数列表

Returns:
处理结果字典
"""
return {"count": len(items), "sum": sum(items)}

def find_user(user_id: int) -> Optional[str]:
"""查找用户

Args:
user_id: 用户ID

Returns:
用户名,如果不存在则返回 None
"""
if user_id == 1:
return "Alice"
return None

小结

本章节介绍了 Python 的模块与包:

  • 模块基础: 模块定义, 导入模块, import 语句, from...import, 模块搜索路径
  • 标准库: os, sys, datetime, random, json, pathlib, collections 等常用模块
  • 第三方库: pip 使用, requirements.txt, 版本管理
  • 虚拟环境: venv, virtualenv, pipenv
  • 包的结构: 包的组织, 相对导入, init.py
  • 包的发布: 项目结构, pyproject.toml, 构建和发布
  • 最佳实践: 组织结构, 命名规范, 导入顺序, 避免循环导入

掌握模块和包的使用,可以帮助你更好地组织代码、提高复用性、构建大型 Python 项目。下一章我们将学习装饰器和生成器,探索 Python 的高级特性。