当前位置:首页>python>Python 零基础100天—Day18 模块与包

Python 零基础100天—Day18 模块与包

  • 2026-10-11 07:37:56
Python 零基础100天—Day18 模块与包

🐍 模块与包 — 代码的积木管理

🕐 预计用时:2-3 小时 | 🎯 目标:掌握 import、__name__、pip 安装第三方库、requirements.txt


📖 今日目录

  1. 为什么要用模块?
  2. import 导入模块
  3. from ... import 精确导入
  4. __name__ 与 __main__
  5. 自定义模块
  6. 包(Package)
  7. pip:第三方库管理
  8. requirements.txt:依赖管理
  9. 实战练习
  10. 今日小结

1. 为什么要用模块?

模块就是"工具箱"——把相关功能打包成一个文件,用的时候导入就行。

# 没有模块:所有代码写在一个文件
# calculator.py → 10000 行代码,找 bug 找到崩溃

# 有模块:按功能拆分
# math_utils.py  → 数学相关函数
# string_utils.py → 字符串相关函数
# file_utils.py  → 文件相关函数
# main.py        → 主程序,导入上面的模块

# 这就是模块的价值:组织代码、复用代码、方便维护
场景
用到的模块
数学计算
math
、random
日期时间
datetime
、time
文件操作
os
、shutil、pathlib
网络请求
requests
、urllib
数据处理
json
、csv
系统相关
sys
、os

2. import 导入模块

📖 基本导入

# 导入整个模块
import math

print(math.pi)            # 3.141592653589793
print(math.sqrt(16))      # 4.0
print(math.ceil(3.2))     # 4
print(math.floor(3.8))    # 3

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

# 每个模块单独一行(推荐,更清晰)
import math
import random
import datetime

📛 给模块起别名

# 用 as 起别名(简化长模块名)
import datetime as dt

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

# 常见别名约定
import numpy as np           # 数据科学标准别名
import pandas as pd          # 数据分析标准别名
import matplotlib.pyplot as plt  # 绑图标准别名

📋 常用内置模块速查

# math — 数学函数
import math
print(math.pi)           # 3.14159...
print(math.e)            # 2.71828...
print(math.sqrt(25))     # 5.0
print(math.log(100, 10)) # 2.0
print(math.factorial(5)) # 120

# random — 随机数
import random
print(random.randint(1, 10))       # 1-10 的随机整数
print(random.random())             # 0-1 的随机浮点数
print(random.choice(["a", "b"]))   # 随机选一个
print(random.shuffle([1,2,3,4]))   # 打乱列表(原地)

# os — 操作系统
import os
print(os.getcwd())                 # 当前工作目录
print(os.listdir("."))             # 列出当前目录文件
print(os.path.exists("test.txt"))  # 文件是否存在
os.makedirs("new_dir", exist_ok=True)  # 创建目录

# sys — 系统相关
import sys
print(sys.version)       # Python 版本
print(sys.platform)      # 操作系统平台
print(sys.path)          # 模块搜索路径
# sys.exit(0)            # 退出程序

3. from ... import 精确导入

📖 导入指定内容

# 只导入需要的部分(不用写模块名前缀)
from math import pi, sqrt

print(pi)         # 3.14159...(不用写 math.pi)
print(sqrt(25))   # 5.0(不用写 math.sqrt)

# 导入多个
from math import pi, sqrt, ceil, floor

# 导入并起别名
from math import sqrt as sq
print(sq(16))  # 4.0

⚠️ 导入全部(不推荐)

# from math import *  # ⚠️ 不推荐!
# 问题:
# 1. 污染当前命名空间(不知道有哪些名字被导入)
# 2. 可能覆盖已有变量
# 3. 代码可读性差(不知道函数来自哪个模块)

# ✅ 推荐写法
from math import sqrt, pi

# ❌ 不推荐
# from math import *

📋 import 三种方式对比

方式
语法
优点
缺点
导入整个模块
import math
清晰、无冲突
每次要写 math.
精确导入
from math import sqrt
简洁、不用前缀
可能命名冲突
导入全部
from math import *
最简洁
❌ 污染命名空间

💡 导入选择原则:
1. 日常开发:import 模块名(清晰明了)
2. 频繁使用某函数:from 模块 import 函数(省代码)
3. from 模块 import *:除非你 100% 确定不会冲突,否则别用


4. __name__ 与 __main__

这是 Python 模块系统的"灵魂特性"——让同一个文件既能被导入,又能直接运行。

# calculator.py
def add(a, b):
    return a + b

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

# 这段代码只有直接运行 calculator.py 时才执行
# 被其他文件 import 时不会执行
if __name__ == "__main__":
    # 测试代码
    print("=== 计算器测试 ===")
    print(f"3 + 5 = {add(3, 5)}")
    print(f"10 - 4 = {subtract(10, 4)}")
# main.py — 使用 calculator 模块
import calculator

# 只能用函数,测试代码不会运行
result = calculator.add(3, 5)
print(f"结果: {result}")  # 结果: 8

🔍 __name__ 的值

# 当文件被直接运行时
# __name__ 的值是 "__main__"

# 当文件被 import 时
# __name__ 的值是模块名(文件名)

# 演示
print(f"当前模块的 __name__: {__name__}")

# 如果直接运行:__name__ = "__main__"
# 如果被导入:__name__ = "calculator"
运行方式
__name__
 的值
if __name__ == "__main__"
python calculator.py"__main__"
✅ 执行
import calculator"calculator"
❌ 跳过

💡 为什么需要 __name__?
1. 模块可以独立运行(测试、演示)
2. 模块可以被导入复用(不执行测试代码)
3. 一个文件两种用途,不用维护两个文件

每个 Python 文件都应该有 if __name__ == "__main__" 块!


5. 自定义模块

📖 创建自己的模块

# 文件:my_utils.py(这就是一个模块)
"""
我的工具模块
提供字符串和数学相关的工具函数
"""

def reverse_string(s):
    """反转字符串"""
    return s[::-1]

def is_palindrome(s):
    """判断是否回文"""
    s = s.lower().replace(" ", "")
    return s == s[::-1]

def factorial(n):
    """计算阶乘"""
    if n <= 1:
        return 1
    return n * factorial(n - 1)

def fibonacci(n):
    """生成斐波那契数列"""
    if n <= 0:
        return []
    if n == 1:
        return [0]
    fib = [0, 1]
    for i in range(2, n):
        fib.append(fib[i-1] + fib[i-2])
    return fib

# 模块的测试代码
if __name__ == "__main__":
    print(reverse_string("hello"))    # olleh
    print(is_palindrome("level"))     # True
    print(factorial(5))               # 120
    print(fibonacci(8))               # [0, 1, 1, 2, 3, 5, 8, 13]
# 文件:main.py(使用自定义模块)
import my_utils

print(my_utils.reverse_string("Python"))   # nohtyP
print(my_utils.is_palindrome("racecar"))   # True

# 或者精确导入
from my_utils import fibonacci
print(fibonacci(10))  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

🔍 模块搜索路径

import sys

# Python 按以下顺序搜索模块:
# 1. 当前目录
# 2. PYTHONPATH 环境变量指定的目录
# 3. 标准库目录
# 4. 第三方库目录(site-packages)

print(sys.path)  # 显示搜索路径

# 如果模块不在搜索路径中,可以手动添加
# sys.path.append("/my/custom/path")

6. 包(Package)

包是"文件夹版的模块"——把多个模块组织成一个目录。

# 包的目录结构
my_project/
├── main.py
└── my_package/          ← 这是一个包(有 __init__.py 的文件夹)
    ├── __init__.py      ← 标识这是一个包(可以为空)
    ├── math_tools.py    ← 子模块
    ├── string_tools.py  ← 子模块
    └── file_tools.py    ← 子模块

# __init__.py(可以为空,也可以有初始化代码)
# 空文件 → 只是标识这是一个包
# 有代码 → 控制包的导入行为
# my_package/math_tools.py
def add(a, b):
    return a + b

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

# my_package/string_tools.py
def capitalize_words(s):
    return s.title()

def count_words(s):
    return len(s.split())

# my_package/__init__.py
# 可以在这里控制导入行为
from .math_tools import add, multiply
from .string_tools import capitalize_words
# main.py — 使用包
# 方式一:导入整个包
import my_package
print(my_package.add(1, 2))

# 方式二:导入子模块
from my_package import math_tools
print(math_tools.multiply(3, 4))

# 方式三:精确导入
from my_package.math_tools import add
print(add(5, 6))

# 方式四:通过 __init__.py 导入的(最简洁)
from my_package import add
print(add(7, 8))

📦 相对导入 vs 绝对导入

# 绝对导入(从项目根目录开始)
from my_package.math_tools import add

# 相对导入(从当前文件位置开始)
# 在 my_package/string_tools.py 中:
from .math_tools import add          # 同级目录
from ..other_package import utils    # 上一级目录

💡 包 vs 模块:
模块 = 一个 .py 文件
包 = 一个包含 __init__.py 的文件夹(里面可以有多个模块)
项目大了就用包来组织,小项目一个模块就够。


7. pip:第三方库管理

pip 是 Python 的"应用商店"——用来安装别人写好的库。

📋 常用 pip 命令

# 安装库
pip install requests
pip install numpy pandas matplotlib  # 一次安装多个

# 指定版本安装
pip install requests==2.31.0         # 精确版本
pip install "requests>=2.28,<3.0"    # 版本范围

# 升级库
pip install --upgrade requests

# 卸载库
pip uninstall requests

# 查看已安装的库
pip list

# 查看某个库的信息
pip show requests

# 搜索库(已弃用,改用 PyPI 网站)
# pip search requests  # ⚠️ 已禁用

# 导出依赖
pip freeze > requirements.txt

# 从文件安装依赖
pip install -r requirements.txt

🌐 国内镜像源(加速下载)

# 临时使用
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

# 永久配置(推荐)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 常用镜像源
# 清华: https://pypi.tuna.tsinghua.edu.cn/simple
# 阿里: https://mirrors.aliyun.com/pypi/simple
# 腾讯: https://mirrors.cloud.tencent.com/pypi/simple
# 华为: https://repo.huaweicloud.com/repository/pypi/simple

📦 常用第三方库推荐

类别
库
用途
Web 开发
requests
HTTP 请求
flask
轻量 Web 框架
django
全栈 Web 框架
数据科学
numpy
数值计算
pandas
数据分析
matplotlib
数据可视化
自动化
selenium
浏览器自动化
beautifulsoup4
网页解析
工具
rich
终端美化输出
python-dotenv
环境变量管理

💡 pip 常见问题:
1. pip 不存在 → 用 pip3 或 python -m pip
2. 下载太慢 → 配置国内镜像源
3. 权限不够 → 加 --user 或用虚拟环境
4. 版本冲突 → 用虚拟环境隔离


8. requirements.txt:依赖管理

requirements.txt 是项目的"购物清单"——记录需要安装哪些库。

# 生成 requirements.txt
pip freeze > requirements.txt

# 文件内容示例
# requests==2.31.0
# flask==3.0.0
# numpy==1.26.2
# pandas==2.1.4

# 别人拿到你的项目后,一键安装所有依赖
pip install -r requirements.txt

📝 requirements.txt 格式

# 精确版本(推荐用于生产环境)
requests==2.31.0
flask==3.0.0

# 最低版本
requests>=2.28.0

# 版本范围
requests>=2.28,<3.0

# 最新版本(不推荐,可能有兼容问题)
requests

# 从 Git 安装
git+https://github.com/user/repo.git

# 注释
requests==2.31.0  # HTTP 请求库
flask==3.0.0      # Web 框架

🏗️ 虚拟环境(最佳实践)

# 创建虚拟环境
python -m venv myenv

# 激活虚拟环境
# Windows:
myenv\Scripts\activate
# macOS/Linux:
source myenv/bin/activate

# 激活后,pip install 只影响当前环境
pip install requests  # 只装在 myenv 里

# 退出虚拟环境
deactivate

# 为什么用虚拟环境?
# 1. 项目 A 需要 requests 2.28,项目 B 需要 requests 2.31
# 2. 不污染系统 Python 环境
# 3. 方便部署和迁移

💡 项目最佳实践:
1. 每个项目一个虚拟环境
2. 维护 requirements.txt
3. 用 pip freeze > requirements.txt 更新依赖
4. 部署时 pip install -r requirements.txt


9. 实战练习

🎯 练习 1:密码工具模块

# password_utils.py
"""
密码工具模块
提供密码生成、强度检查、哈希等功能
"""
import random
import string
import hashlib

def generate_password(length=16, use_special=True):
    """生成随机密码"""
    chars = string.ascii_letters + string.digits
    if use_special:
        chars += "!@#$%^&*"

    # 确保至少包含各种字符
    password = [
        random.choice(string.ascii_uppercase),
        random.choice(string.ascii_lowercase),
        random.choice(string.digits),
    ]
    if use_special:
        password.append(random.choice("!@#$%^&*"))

    # 填充剩余长度
    for _ in range(length - len(password)):
        password.append(random.choice(chars))

    random.shuffle(password)
    return "".join(password)

def check_strength(password):
    """检查密码强度"""
    score = 0
    feedback = []

    if len(password) >= 8:
        score += 1
    else:
        feedback.append("长度不足8位")

    if any(c.isupper() for c in password):
        score += 1
    else:
        feedback.append("缺少大写字母")

    if any(c.islower() for c in password):
        score += 1
    else:
        feedback.append("缺少小写字母")

    if any(c.isdigit() for c in password):
        score += 1
    else:
        feedback.append("缺少数字")

    special = "!@#$%^&*()_+-=[]{}|;:',.<>?"
    if any(c in special for c in password):
        score += 1
    else:
        feedback.append("缺少特殊字符")

    levels = {0: "极弱", 1: "弱", 2: "一般", 3: "中等", 4: "强", 5: "极强"}
    return score, levels[score], feedback

def hash_password(password, algorithm="sha256"):
    """哈希密码"""
    h = hashlib.new(algorithm)
    h.update(password.encode("utf-8"))
    return h.hexdigest()

# 测试代码
if __name__ == "__main__":
    print("=== 密码工具测试 ===")

    # 生成密码
    for i in range(3):
        pwd = generate_password(12)
        score, level, _ = check_strength(pwd)
        print(f"  {pwd} | {level} ({score}/5)")

    # 检查强度
    test_pwd = "MyP@ss2024!"
    score, level, feedback = check_strength(test_pwd)
    print(f"\n密码: {test_pwd}")
    print(f"强度: {level} ({score}/5)")
    print(f"哈希: {hash_password(test_pwd)[:32]}...")

🎯 练习 2:简易包结构

# 项目结构
# my_tools/
# ├── __init__.py
# ├── math_tools.py
# ├── text_tools.py
# └── list_tools.py

# my_tools/__init__.py
"""
我的工具包
"""
from .math_tools import average, percentage
from .text_tools import word_count, char_count
from .list_tools import flatten, unique

# my_tools/math_tools.py
def average(numbers):
    """计算平均值"""
    return sum(numbers) / len(numbers) if numbers else 0

def percentage(part, total):
    """计算百分比"""
    return round(part / total * 100, 2) if total else 0

# my_tools/text_tools.py
def word_count(text):
    """统计单词数"""
    return len(text.split())

def char_count(text, include_spaces=True):
    """统计字符数"""
    if include_spaces:
        return len(text)
    return len(text.replace(" ", ""))

# my_tools/list_tools.py
def flatten(nested):
    """扁平化嵌套列表"""
    result = []
    for item in nested:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result

def unique(items):
    """去重并保持顺序"""
    seen = set()
    result = []
    for item in items:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

# 使用示例
from my_tools import average, word_count, flatten

print(average([85, 90, 78, 92]))    # 86.25
print(word_count("hello world python"))  # 3
print(flatten([[1, 2], [3, [4, 5]]]))    # [1, 2, 3, 4, 5]

🎯 练习 3:配置管理器

# config_manager.py
"""
配置管理模块
支持 JSON 配置文件的读写和管理
"""
import json
import os

class ConfigManager:
    """配置管理器"""

    def __init__(self, config_file="config.json"):
        self.config_file = config_file
        self.config = {}
        self.load()

    def load(self):
        """加载配置文件"""
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, "r", encoding="utf-8") as f:
                    self.config = json.load(f)
            except json.JSONDecodeError as e:
                print(f"⚠️ 配置文件格式错误: {e}")
                self.config = {}
        else:
            self.config = {}

    def save(self):
        """保存配置到文件"""
        with open(self.config_file, "w", encoding="utf-8") as f:
            json.dump(self.config, f, indent=2, ensure_ascii=False)

    def get(self, key, default=None):
        """获取配置项"""
        return self.config.get(key, default)

    def set(self, key, value):
        """设置配置项"""
        self.config[key] = value
        self.save()  # 自动保存

    def delete(self, key):
        """删除配置项"""
        if key in self.config:
            del self.config[key]
            self.save()
            return True
        return False

    def keys(self):
        """获取所有配置项名称"""
        return list(self.config.keys())

    def __str__(self):
        return json.dumps(self.config, indent=2, ensure_ascii=False)

# 测试
if __name__ == "__main__":
    config = ConfigManager("test_config.json")

    # 设置配置
    config.set("app_name", "我的应用")
    config.set("version", "1.0.0")
    config.set("debug", True)
    config.set("max_retries", 3)

    # 读取配置
    print(f"应用名: {config.get('app_name')}")
    print(f"版本: {config.get('version')}")
    print(f"调试模式: {config.get('debug')}")

    # 显示所有配置
    print(f"\n所有配置:\n{config}")

    # 删除配置
    config.delete("debug")
    print(f"\n删除后:\n{config}")

10. 今日小结

知识点
核心内容
import
import module
、import module as alias
from ... import
from module import func
、精确导入
__name__
直接运行 = "__main__",被导入 = 模块名
自定义模块
一个 .py 文件就是一个模块
包
有 __init__.py 的文件夹,组织多个模块
pip
install
 / uninstall / list / freeze
镜像源
清华/阿里/腾讯源加速下载
requirements.txt
依赖清单,pip install -r 一键安装
虚拟环境
python -m venv
,项目隔离

🧠 记忆口诀:
import 导模块,from 精确取。
name 是 main,独立运行起。
init 标识包,pip 装工具。
freeze 列清单,venv 隔离地。

🔮 预告: Day 19 推导式 — 列表/字典/集合推导式、生成器表达式。Python 最优雅的语法糖!

轻松时刻:

请在微信客户端打开

最新文章

随机文章