Python学习笔记
https://www.python.org/ (opens new window)
# 模块(Module)
# 什么是模块
Python 的模块(Module)是 Python 中组织代码的基本单位。
模块就是一个以 .py 结尾的 Python 文件,里面可以包含:
- 变量
- 函数
- 类
- 可执行语句
# 为什么使用模块
- 代码复用 可以在多个程序中重复使用同一份代码。
- 命名空间隔离 不同模块中的变量、函数不会互相冲突。
- 结构清晰 把功能拆分成多个模块,便于维护和协作。
# 模块的分类
# 标准库模块
标准库模块:Python 自带,无需安装。
- 内置模块(Built-in modules):编译进 Python 解释器,无 .py 文件
- 非内置标准库模块:以 .py 文件形式随 Python 分发
所有内置模块都是标准库,但标准库不全是内置模块。
import sys
import math
import os
import json
# 方法一:sys.builtin_module_names
# 打印所有内置模块名,会输出一个元组
print(sys.builtin_module_names)
# 模块名 in sys.builtin_module_names,如果一个模块名在这个元组里的 = 内置模块,不在的 = 非内置(即使是标准库)。
print('math' in sys.builtin_module_names)
print('os' in sys.builtin_module_names)
print('json' in sys.builtin_module_names)
# 方法二:看 __file__ 属性
# 没有 __file__ 属性 → 内置模块(代码编译在解释器里,没有独立文件)
# 有 __file__ → 非内置(有对应的 .py 文件)
try:
print(math.__file__) # AttributeError 或 None → 内置模块
except AttributeError:
pass
print(os.__file__) # /usr/lib/python3.12/os.py → 非内置
print(json.__file__) # /usr/lib/python3.12/json/__init__.py → 非内置
# 方法三:使用hasattr函数
print(hasattr(math, '__file__')) # # hasattr(模块, '__file__') → False 就是内置
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 自定义模块
自定义模块:用户自己编写的Python 文件。
# 第三方模块
第三方模块:需要安装,例如:pip install requests
# 如何导入模块
以导入自定义模块fibonacci.py为例。fibonacci.py内容如下:
# Fibonacci numbers module
def print_fib(n):
"""Write Fibonacci series up to n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def get_fib(n):
"""Return Fibonacci series up to n."""
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
# 控制 `from 模块名 import *` 的行为(限制可以导入哪些内容)
__all__ = ['print_fib', 'get_fib']
if __name__ == '__main__':
# 直接运行 `fibonacci.py` 会执行以下测试代码,被导入时不会自动执行
print_fib(5)
result = get_fib(5)
print(result)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- 基本导入:
import 模块名
import fibonacci
fibonacci.print_fib(5)
2
3
- 给模块起别名:
import 模块名 as 别名
import fibonacci as fibo
fibo.print_fib(5)
2
3
- 导入指定内容:
from 模块名 import 具体内容1, 具体内容2, ...
from fibonacci import print_fib
print_fib(5)
2
3
- 给指定内容起别名:
from 模块名 import 具体内容1 as 别名1, 具体内容2 as 别名2, ...
from fibonacci import print_fib as pf
pf(5)
2
3
- 导入所有内容(不推荐,容易造成命名冲突,一般不建议使用。):
from 模块名 import *
from fibonacci import *
print_fib(5)
2
3
# 模块属性:__all__ —— 控制"导出什么"
问题场景
假设你写了这个包:
# mypkg/utils.py
def helper():
pass
def _internal_helper(): # 内部函数,不希望被外部用
pass
2
3
4
5
6
7
用户执行:
from mypkg.utils import *
结果 _internal_helper 也被导入了!这不是你想要的。
解决方案:__all__
# mypkg/utils.py
__all__ = ["helper"] # 只有 helper 会被 * 导入
def helper():
pass
def _internal_helper(): # 内部函数,不希望被外部用
pass
2
3
4
5
6
7
8
9
现在:
from mypkg.utils import *
helper() # ✅ 正常
_internal_helper() # ❌ NameError
2
3
重要细节
| 情况 | from xxx import * 的行为 |
|---|---|
定义了 __all__ | 只导入 __all__ 里列出的名字 |
没定义 __all__ | 导入所有不以下划线 _ 开头的名字 |
| 名字以下划线开头 | 默认不会被 * 导入(约定俗成的"私有") |
⚠️ __all__ 只影响 import *,不影响普通导入:
from mypkg.utils import _internal_helper # ✅ 仍然可以
一句话总结:__all__ = 白名单,控制 import * 时导出哪些名字
# 模块属性:__name__ —— 控制"我是谁、我怎么被用的"
每个模块都有一个内置变量 __name__:
- 如果模块是被直接运行的:
__name__ == "__main__" - 如果模块是被导入的:
__name__ == 模块名
# 模块的搜索路径
执行 import xxx 时,解释器按顺序来:
- 内置模块(在
sys.builtin_module_names里,如sys、math)→ 命中就用,不走路径 sys.path[0]:空字符串''表示「当前执行脚本所在目录」;交互式/-c下是当前工作目录PYTHONPATH环境变量里列出的目录(如果有)- 标准库目录(Python 安装目录下的
lib/pythonX.Y/) site-packages(含全局、用户级、虚拟环境级)——第三方包所在地.pth文件里注册的额外路径(site 模块启动时读取)
一旦在某一步找到同名模块/包,立刻停止,后面不再看。所以「当前目录 > PYTHONPATH > site-packages」。
# 包(Package)
# 什么是包
包是包含多个模块的文件夹,必须包含 __init__.py 文件( __init__.py 文件可以为空)。
目录结构示例:
my_package/
├── __init__.py
├── module_a.py
└── module_b.py
2
3
4
# 如何导入包
导入方式:
- 基本导入:
import 包名:不等于自动能访问子模块
import 包名.模块名
- 起别名导入:
import 包名 as 别名
import 包名.模块名 as 别名
导入指定内容:
from 包名 import 模块名1, 模块名2, ...from 包名.模块名 import 具体内容1, 具体内容2, ...给指定内容起别名:
from 包名 import 模块名1 as 别名1, 模块名2 as 别名2, ...from 包名.模块名 import 具体内容1 as 别名1, 具体内容2 as 别名2, ...导入所有内容(不推荐,容易造成命名冲突,一般不建议使用。):
from 包名 import *:受包/__init__.py的__all__影响from 包名.模块名 import *:受 模块__all__影响;无则导入非下划线开头名字
# 包初始化文件:__init__.py
为什么需要它?
Python 3.3 之前,没有 __init__.py 的文件夹不被视为包,你没法用 import 导入里面的模块。
Python 3.3+ 引入了"命名空间包",技术上可以没有它了。但实际项目中几乎都会保留,因为它有三个核心作用:
作用 1:包的初始化代码
当包被导入时,__init__.py 里的代码会自动执行一次
这适合放:
- 包的版本号
- 全局配置
- 需要在导入时自动执行的初始化逻辑
作用 2:控制 from 报名 import * 的行为
在 __init__.py 里定义 __all__
作用 3:简化导入路径(最常用)
假设你的包结构是这样的:
mypkg/
├── __init__.py
├── utils.py # 里面有函数 helper()
├── models.py # 里面有类 User()
└── views.py # 里面有函数 render()
2
3
4
5
没有 __init__.py 帮忙时,用户得这么导入:
from mypkg.utils import helper
from mypkg.models import User
from mypkg.views import render
2
3
在 __init__.py 里做"重新导出":
# mypkg/__init__.py
from .utils import helper
from .models import User
from .views import render
2
3
4
5
用户就可以这样用:
from mypkg import helper, User, render
甚至:
import mypkg
mypkg.helper()
2
这就是很多流行库(如 requests、flask)让你能用极短路径导入的原因。
作用 4:作为包的"门面"(Facade 模式)
你可以在 __init__.py 里只暴露对外 API,隐藏内部实现细节:
# mypkg/__init__.py
from .public_api import do_something, do_another_thing
__version__ = "2.0.0"
2
3
4
5
用户完全不需要知道 public_api.py 的存在,只管:
import mypkg
mypkg.do_something()
2
内部结构怎么改都不影响用户代码。
一句话总结:__init__.py = 包的"入口文件",负责初始化 + 简化导入 + 隐藏实现
# 判断电脑是否安装 Python & 定位 Python 环境
# 1. 快速判断:有没有装 Python?
在终端 / 命令行执行:
python --version
python3 --version # macOS/Linux 专用
py --version # Windows 专用
2
3
看到类似 Python 3.11.6 → 已安装,且当前在 PATH 中可找到。
看到 command not found / 'python' is not recognized... → 不一定没装,可能是只装了 python3、py,或没加入 PATH。
若已安装,可进一步列出所有已注册版本:
py --list
也可进入交互解释器验证:
python
看到 >>> 提示符即表示可用,输入 exit() 退出。
# 2. 看装在哪里:which / where
当我们输入:
which python # Linux / macOS
where python # Windows
2
系统会按 PATH 环境变量的顺序查找,告诉你当前实际调用的 python 在哪里。
看到的会是具体路径,例如:
/usr/bin/python/usr/local/bin/pythonC:\Python311\python.exe/home/user/venv/bin/python
👉 也就是说,直接敲 python 时,用的就是这里显示的第一个。即当前 python 主解释器。
如果激活了虚拟环境,通常会看到 venv 里的那个路径,因为它被临时放到了 PATH 最前面。
# 3. 终极确认:当前真正使用的是哪个解释器
直接敲 python 用的就是 which/where 显示的第一个;激活虚拟环境后会临时变成 venv 里的那个。
使用以下命令可以最终确认。输出的是当前 python 命令实际指向的解释器绝对路径,最准确。
python -c "import sys; print(sys.executable)"
也可顺手看版本与路径:
python -c "import sys; print(sys.version); print(sys.executable)"
# 4. 同一台电脑安装 多个 Python 版本
Python 版本之间“物理隔离”,靠路径区分,而不是靠覆盖。
- 每个 Python 版本安装在不同的目录
- 每个 Python 自带:
- 自己的解释器
- 自己的
pip - 自己的
site-packages(第三方库)
- 操作系统通过 PATH 顺序 或 启动器 决定“用哪一个”
# 5. py.exe
py.exe 是 Windows 上 Python 官方提供的“Python 启动器(Python Launcher)”。
- 位置:
C:\Windows\py.exe - 作用:在 Windows 上统一管理多个已安装的 Python 版本
- 本质:一个小型可执行程序,不负责运行代码,只负责**“帮你选一个 Python 去运行”**
✅ 1. 列出所有已安装的 Python
py --list
👉 这是判断“Windows 上到底装了哪些 Python”的最权威方式
✅ 2. 指定版本运行 Python
py -3.12 main.py
py -3.11 main.py
2
👉 完全不依赖 PATH
✅ 3. 运行模块(等价于 python -m)
py -3.12 -m pip install requests
py -3.11 -m venv .venv
2
👉 这是 Windows 上最稳的写法
✅ 4. 作为 .py 文件的默认打开方式
hello.py → py.exe hello.py
👉 Windows 默认把 .py 文件关联到 py.exe, 而 py.exe 会根据文件里的 shebang 自动选版本。
脚本里的 shebang:
#!python3.11
例如:
#!python3.13
import sys
print(sys.version)
print(sys.executable)
2
3
4
5
| 对比项 | py | python |
|---|---|---|
| 来源 | Python 官方启动器 | 某个 Python 安装目录里的解释器 |
| 是否依赖 PATH | ❌ 不依赖 | ✅ 依赖 |
| 是否支持多版本 | ✅ 原生支持 | ❌ 只能用一个 |
| 是否推荐 | ✅ Windows 首选 | ⚠️ 有 PATH 风险 |
| 是否稳定 | ✅ 非常稳定 | ⚠️ 可能指向错版本 |
✅ Windows 上,优先用 py
# python -m
# python -m 是啥?
👉 用“我指定的这个 python”,去跑一个模块。
python -m 模块名
大白话解释:
用这个 python
→ 找到模块
→ 执行它的
__main__.py
python -m 模块名 中,前面的 python:
不写路径 → PATH 里第一个 python
写路径 → 你指定的 python
# 为什么要用它?
核心目的只有一个:
✅ 防止用错 python / pip
# 经典用法 1:创建虚拟环境
python -m venv .venv
大白话解释:
- 用当前这个 python
- 复制一份它自己
- 建一个独立的
.venv - 以后包装在这个小房间里,不影响系统
激活:
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
2
3
4
5
✅ 激活虚拟环境,本质就是改 PATH,把 venv 的 python 插到最前面
# 经典用法 2:装包(最重要)
python -m pip install requests
大白话解释:
用我前面这个
python→ 运行它自带的
pip→ 把包装进它自己的
site-packages
✅ 保证:
python和pip是一对import requests一定能找到
为什么不直接用 pip?
| 写法 | 大白话 |
|---|---|
pip install xxx | 用 PATH 里第一个 pip,不知道它跟谁是一对 |
python -m pip install xxx | 明确用这个 python 的 pip ✅ |
👉 pip 只是 python 的一个模块,python 才是老大。
# PyPI(Python Package Index,Python 包索引)官网
https://pypi.org/ (opens new window) 就是 PyPI(Python Package Index,Python 包索引) 的官方网站,由 Python 软件基金会(PSF)维护,是 Python 生态的默认公共包仓库。
- 对开发者(使用者):它是"应用商店"。你运行
python -m pip install requests,pip 默认就是从 pypi.org 下载包及其依赖,再装进对应环境的site-packages。 - 对作者(发布者):它是"发布平台"。开发者用
twine/hatch/flit把打好的包(wheel 或 sdist)传上去,全世界的 Python 用户都能pip install到。
# pip(Package Installer for Python)
pip, Package Installer for Python,Python包管理器。
# pip --version
查看 pip 版本。用于确认 pip 是否存在、版本号,以及它绑定到哪个 Python 解释器/路径。
pip --version
# pip config
查看当前 pip 配置。可以看到是否已经配置了 global.index-url 等。
pip config list
配置镜像源。修改当前用户/环境层面的 pip 配置,之后执行 pip install 包名 会默认走这个镜像。
pip config set global.index-url 地址
常用国内镜像,都是同步 pypi.org 的,配置时地址一般要指向 /simple 结尾的索引地址。
- 清华大学 TUNA:https://pypi.tuna.tsinghua.edu.cn/simple
- 阿里云:https://mirrors.aliyun.com/pypi/simple/
- 中国科学技术大学:https://pypi.mirrors.ustc.edu.cn/simple/
- 腾讯云:https://mirrors.cloud.tencent.com/pypi/simple/
- 华为云:https://repo.huaweicloud.com/repository/pypi/simple/
恢复官方默认地址。恢复后,pip install 默认从官方 PyPI (https://pypi.org/) 获取。
pip config unset global.index-url
# pip install
pip install 会把包装进当前 pip 绑定的那个 Python 解释器对应的 site-packages。常见位置:
- 系统全局(全局环境/系统环境):
Linux /usr/local/lib/python3.X/site-packages,Windows C:\Python3X\Lib\site-packages - 用户级(
pip install --user):Linux ~/.local/lib/python3.X/site-packages,Windows %APPDATA%\Python\Python3X\site-packages - 虚拟环境:
项目/.venv/lib/python3.X/site-packages

安装最新版。默认从 PyPI(或你配置的镜像源)安装第三方包的最新稳定版本。
pip install 包名
安装指定版本。如果已经安装了其他版本,pip 通常会先卸载当前版本,再安装指定版本。版本号必须是 PyPI/镜像源中存在的版本。
pip install 库名==版本号
也支持版本范围。注意:在 bash/zsh 等终端里,含 >, <, = 的表达式建议加引号,避免被 shell 误解析。
pip install "numpy>=1.21.0"
pip install "flask<3.0"
pip install "requests>=2.20.0,<3.0"
2
3
临时使用镜像安装。只对本次安装生效,不会修改全局配置。
pip install -i 镜像地址 包名
升级包。
- 如果库已安装:升级到索引源上的最新版本。
- 如果库未安装:相当于 pip install 库名,直接安装最新版。
pip install --upgrade 库名
pip install -U 库名
2
按依赖文件安装。读取文件中的包名和版本约束,批量安装依赖。
pip install -r requirements.txt
pip install -r ./requirements.txt # 指定路径
2
requirements.txt 用来记录当前 Python 环境里需要的第三方包及版本,方便别人或自己在另一个环境里一键安装,保证依赖一致。常用于项目环境复现、部署、协作。
每行一个依赖,示例:
requests==2.28.1
numpy>=1.21.0
flask==2.2.5
# 工具包
pytest>=7.0.0
2
3
4
5
说明:
==:固定版本>=:最低版本- 也可以写
<,<=,~=等版本约束 #后面可写注释
# pip freeze
导出当前环境依赖。会把当前环境已安装包和精确版本写入文件。
pip freeze > requirements.txt
pip freeze > ./requirements.txt
2
注意:pip freeze 通常会导出当前环境中很多包,包括间接依赖。若想让依赖文件更干净,可以手动维护只写项目直接依赖;或者配合虚拟环境使用,避免混入全局包。
# pip uninstall
卸载包。从当前 Python 环境中卸载指定的第三方包。
pip uninstall 包名
# pip list
查看已安装包。列出当前环境已安装的所有第三方包及版本。
pip list
# pip show
看某个包信息。
pip show 包名