Files
python/20-24/08model-package.py
2026-05-06 11:21:42 +08:00

528 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 概述
# 模块和包是 Python 中组织代码的重要方式,它们让代码更加结构化、可维护和可重用。掌握模块和包的使用是 Python 编程的基础技能。
# 2.核心概念
# 模块:包含 Python 定义和语句的 .py 文件
# 包:包含多个模块的目录,必须有 __init__.py 文件
# 命名空间:每个模块和包都有独立的命名空间
# 导入:将模块或包引入当前程序的过程
# 模块(Module
# 3.1.什么是模块?
# 模块是一个包含 Python 定义和语句的 .py 文件,可以包含:
# 函数定义
# 类定义
# 变量
# 可执行代码
# 3.2.模块的优势
# 代码复用:公共函数/类可以集中管理
# 命名空间隔离:避免命名冲突
# 可维护性:分文件组织更易管理大型项目
# 模块化设计:提高代码的模块化程度
# 创建和使用模块
# 创建模块
# mymodule.py
def hello():
print("Hello from mymodule!")
def add(a, b):
return a + b
class Calculator:
def multiply(self, a, b):
return a * b
# 导入模块
# main.py
import mymodule
# 使用模块中的函数和类
mymodule.hello()
result = mymodule.add(3, 4)
calc = mymodule.Calculator()
print(calc.multiply(2, 3))
# 导入特定成员
# 导入特定函数和类
from mymodule import hello, add, Calculator
# 直接使用,无需模块名前缀
hello()
result = add(3, 4)
calc = Calculator()
# 模块查找路径
# Python 按照以下顺序查找模块:
# 当前程序所在目录
# PYTHONPATH 环境变量指定的目录
# Python 安装时的标准库目录
import sys
# 查看模块搜索路径
print(sys.path)
# 模块命名规范
# 使用小写字母和下划线
# 避免与标准库同名
# 导入时无需写 .py 后缀
# 导入方式详解
# 导入整个模块
# import math
# # 通过模块名访问成员
# print(math.sqrt(16)) # 输出 4.0
# print(math.pi) # 输出 3.141592653589793
# 1.优点
# 命名空间清晰:明确成员来自哪个模块
# 避免命名冲突:同名函数不会冲突
# 代码可读性:容易理解函数来源
# 2.适用场景
# 使用模块中多个成员时
# 需要明确函数来源时
# 避免命名冲突时
# 导入所有成员(import *
# from 模块名 import *
# mymodule.py
def foo():
print("foo")
def bar():
print("bar")
from mymodule import *
foo() # 输出 foo
bar() # 输出 bar
# 控制导入内容
# mymodule.py
__all__ = ["foo"] # 只允许导入 foo
def foo():
print("foo")
def bar():
print("bar")
# 注意事项
# 不推荐使用:容易造成命名冲突
# 仅限模块:不适用于包
# 命名空间污染:直接暴露在当前命名空间
# 可读性差:难以确定函数来源
# 推荐做法
# 推荐:明确导入
from mymodule import foo, bar
# 推荐:导入整个模块
import mymodule
# 使用别名
# import 模块名 as 新名字
# from 模块名 import 成员 as 新名字
# 示例
import numpy as np
import matplotlib.pyplot as plt
from math import factorial as fact
# 使用别名
arr = np.array([1, 2, 3])
plt.plot([1, 2, 3])
result = fact(5)
# 别名优势
# 代码简洁:缩短长模块名
# 避免冲突:解决命名冲突
# 社区约定:遵循常用别名习惯
# 常用别名
# numpy → np
# pandas → pd
# matplotlib.pyplot → plt
# tensorflow → tf
# 模块的 __name__ 属性
# __name__ 属性用于判断模块是被直接运行还是被导入:
# 直接运行时:__name__ 为 "__main__"
# 被导入时:__name__ 为模块名称
# mymodule.py
def func():
print("hello")
if __name__ == "__main__":
# 只在直接运行时执行
func()
# 使用场景
# 运行方式 __name__ 值 作用
# 直接运行 "__main__" 执行主流程
# 被导入 模块名 提供接口
# 最佳实践
# 所有模块入口脚本都使用 if __name__ == "__main__":
# 既可作为工具库导入,也可作为脚本运行
# 提高代码的灵活性和可测试性
# 包(Package
# 5.1.什么是包?
# 包是组织多个模块的目录,包含:
# 多个模块(.py 文件)
# 子包(嵌套目录)
# __init__.py 文件(必需)
# 5.2.包的优势
# 项目结构清晰:分层组织代码
# 避免命名冲突:独立的命名空间
# 便于团队开发:模块化协作
# 组件重用:可复用的代码单元
# 包的结构
# mypackage/
# ├── __init__.py # 包初始化文件(必需)
# ├── module1.py # 模块1
# ├── module2.py # 模块2
# └── subpackage/ # 子包
# ├── __init__.py # 子包初始化文件
# └── module3.py # 子包模块
# 创建包结构
# 目录结构
# myproject/
# ├── main.py
# └── mypackage/
# ├── __init__.py
# ├── module1.py
# ├── module2.py
# └── subpackage/
# ├── __init__.py
# └── module3.py
# 初始化文件 __init__.py
# mypackage/__init__.py
"""mypackage 包的初始化文件"""
__version__ = "1.0.0"
__author__ = "Your Name"
# 导入包中的模块,方便用户使用
from .module1 import function1
from .module2 import Class2
# 定义包级别的变量
package_variable = "这是包变量"
print("mypackage 包被导入")
# 包中的模块
# mypackage/module1.py
def function1():
return "这是 module1 的 function1"
def helper_function():
return "辅助函数"
# mypackage/module2.py
class Class2:
def __init__(self, value):
self.value = value
def display(self):
return f"Class2 的值: {self.value}"
# mypackage/subpackage/module3.py
def function3():
return "这是子包中的 function3"
# 导入包和模块语法
# 导入整个包
# 导入整个包(执行 __init__.py
import mypackage
# 导入包内模块
# 导入包内指定模块
from mypackage import module1
# 导入包中模块的成员
from mypackage.module1 import function1
# 导入子包
# 导入子包中的模块
from mypackage.subpackage import module3
# 导入子包模块的成员
from mypackage.subpackage.module3 import function3
# 相对导入与绝对导入
# 绝对导入
# 从项目根包开始写完整路径:
# 从 mypackage 包中的 module1 模块导入 function1 函数
from mypackage.module1 import function1
# 从子包中导入
from mypackage.subpackage.module3 import function3
# 相对导入
# 在包内部使用点号语法:
# 同级目录
from . import module1
# 上一级包
from .. import module2
# 同级模块
from .module1 import func
# 上级包的子包
from ..subpackage import module3
# 注意事项
# 相对导入只能用于包内部模块
# 不能在最顶层脚本(main.py)中使用
# 包内各文件的相对路径以包目录为基准
# __init__.py 的作用
# 声明包:标识目录为 Python 包
# 初始化操作:包级变量、配置、统一导入
# 控制导入:通过 __all__ 列表控制可见成员
# 导入包和模块示例
# main.py
# 导入包中的特定模块
from mypackage import module1
print(module1.function1())
# 导入包中的特定函数/类
from mypackage.module2 import Class2
obj = Class2(42)
print(obj.display())
# 导入子包中的模块
from mypackage.subpackage import module3
print(module3.function3())
# 使用 __init__.py 中导入的内容
from mypackage import function1
print(function1())
# 导入包变量
import mypackage
print(mypackage.package_variable)
# 高级导入技巧
# 相对导入
# 相对导入在包内部使用点号语法引用同包或父包内容:
# 基本语法
# from . import xxx:从当前包导入
# from .. import xxx:从父包导入
# from .subpackage import yyy:从子包导入
# mypackage/
# ├── __init__.py
# ├── module1.py
# ├── module2.py
# └── subpackage/
# ├── __init__.py
# └── module3.py
# module1.py
# from . import module2 # 导入同级模块
# from .subpackage import module3 # 导入子包模块
# def function1():
# return "这是 module1 的 function1"
# 注意事项
# 只能在包内部使用
# 不能在主程序(main.py)中使用
# 有助于包的重命名与迁移
# 点数与目录层次相关
# 动态导入
# 动态导入在程序运行时根据需要导入模块,常用于插件系统和可扩展框架。
# .使用 __import__()
module_name = "math"
math_module = __import__(module_name)
print(math_module.sqrt(9)) # 输出: 3.0
# 使用 importlib
import importlib
# 导入标准库模块
module = importlib.import_module("json")
data = module.loads('{"a": 1}')
print(data) # 输出: {'a': 1}
# 导入包内模块
module_name = "mypackage.module1"
mod = importlib.import_module(module_name)
result = mod.function1()
print(result) # 输出: 这是 module1 的 function1
# 动态导入优势
# 按需加载:减少资源占用
# 插件机制:支持动态扩展功能
# 配置驱动:根据配置加载不同组件
# 注意事项
# 确保模块名合法且可找到
# 过度使用影响代码可读性
# 仅在确有需要时使用
# 模块搜索路径
# 搜索路径顺序
# Python 按以下顺序查找模块:
# 当前脚本所在目录
# 标准库路径(如 /usr/lib/python3.x
# 第三方库目录(如 site-packages
# PYTHONPATH 环境变量指定的路径
# 查看和修改搜索路径
import sys
# 查看当前搜索路径
print(sys.path)
# 临时添加自定义路径
sys.path.append("/path/to/your/modules")
# 模块查找优先级
# 内存缓存:已加载的模块(防止重复导入)
# 内建模块:如 sys、os
# sys.path 目录:按顺序逐一查找
# 最佳实践
# 合理组织项目结构
# 使用 __init__.py 标识包
# 规范包和模块命名
# 避免随意修改 sys.path
# 创建可安装的包
# 包目录结构
# mypackage/
# ├── mypackage/
# │ ├── __init__.py
# │ ├── module1.py
# │ └── module2.py
# ├── tests/
# │ └── test_module1.py
# ├── setup.py
# ├── README.md
# └── LICENSE
# 创建步骤
# 组织包目录结构
# 外层目录:项目根目录
# 内层目录:实际包目录(包含 __init__.py
# tests/:测试代码目录
# 创建 __init__.py
# 声明目录为 Python 包
# 可包含包级初始化逻辑
# 编辑 setup.py 配置
# 声明包名称、版本、依赖等元信息
# (可选)增加 MANIFEST.in
# 包含非 Python 文件(数据文件、README 等)
# 安装和发布
# 本地安装:pip install . 或 pip install -e .
# 发布到 PyPIpython setup.py sdist bdist_wheel 和 twine upload dist/*
# 设置文件 setup.py
# setup.py
from setuptools import setup, find_packages
setup(
name="mypackage",
version="1.0.0",
description="一个示例包",
author="Your Name",
packages=find_packages(),
install_requires=[
"requests>=2.25.1",
"numpy>=1.19.5",
],
python_requires=">=3.6",
)
# 安装和发布
# 开发模式安装(可编辑模式)
pip install -e .
# 构建分发包
python setup.py sdist bdist_wheel
# 上传到PyPI
twine upload dist/*
# 最佳实践
# 1.命名规范
# 模块命名:使用小写字母和下划线
# 包命名:使用小写字母,避免使用下划线
# 避免冲突:不与标准库同名
# 2.导入规范
# 导入顺序:标准库 → 第三方库 → 本地模块
# 避免循环导入:模块间相互导入
# 使用 if __name__ == "__main__":区分直接运行和导入
# 导入顺序示例
# 标准库
import os
import sys
from datetime import datetime
# 第三方库
import requests
import numpy as np
# 本地模块
from mypackage import module1
from mypackage.subpackage import module2
# 项目组织
# 合理使用包和模块
# 避免过深的嵌套结构
# 保持模块功能单一
# 编写清晰的文档和注释