跳到主要内容

第10章:模块与包

作为 Java 开发者,你已经熟悉了 Java 的包系统和模块系统。Python 也有自己的模块和包系统,本章将详细对比两种语言的模块与包。

10.1 模块系统对比

Java 模块系统

  • :使用 package 声明,通过目录结构组织
  • 导入:使用 import 语句导入包或类
  • 模块:Java 9+ 引入了模块系统(JPMS),使用 module-info.java 定义
  • 可见性:通过访问修饰符控制(public, protected, private)

Python 模块系统

  • 模块:一个 .py 文件就是一个模块
  • :包含 __init__.py 文件的目录就是一个包
  • 导入:使用 import 语句导入模块或包
  • 可见性:通过命名约定控制(下划线前缀)

对比

特性JavaPython
模块定义类文件.py 文件
包定义目录 + package 声明目录 + __init__.py 文件
导入语句import package.Classimport modulefrom module import function
可见性访问修饰符命名约定(_prefix)
模块系统JPMS(Java 9+)简单的模块导入系统

10.2 模块导入

Java 导入

// 导入单个类
import java.util.ArrayList;

// 导入整个包
import java.util.*;

// 静态导入
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

// 使用导入的类
ArrayList<String> list = new ArrayList<>();
double radius = 5;
double area = PI * radius * radius;
double length = sqrt(25);

Python 导入

# 导入整个模块
import math

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

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

# 使用别名
import math as m
from math import pi as PI

# 使用导入的模块
radius = 5
area = math.pi * radius * radius
length = sqrt(25)
print(m.pi) # 使用别名
print(PI) # 使用重命名的变量

对比

操作JavaPython
导入模块import packageimport module
导入特定成员import package.Classfrom module import member
导入所有成员import package.*from module import *
使用别名不支持import module as alias
静态导入import static直接导入函数和变量

10.3 包的结构

Java 包结构

com/
└── example/
├── model/
│ ├── User.java
│ └── Product.java
├── service/
│ ├── UserService.java
│ └── ProductService.java
└── Main.java

Python 包结构

myapp/
├── __init__.py
├── model/
│ ├── __init__.py
│ ├── user.py
│ └── product.py
├── service/
│ ├── __init__.py
│ ├── user_service.py
│ └── product_service.py
└── main.py

对比

特性JavaPython
包标识目录结构 + package 声明目录结构 + __init__.py 文件
包导入import com.example.model.Userfrom myapp.model import user
包初始化__init__.py 文件中的代码在包导入时执行
包级别变量静态变量__init__.py 中的变量

10.4 创建和使用模块

Java 模块创建

// com/example/model/User.java
package com.example.model;

public class User {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}

// com/example/Main.java
package com.example;

import com.example.model.User;

public class Main {
public static void main(String[] args) {
User user = new User("Alice", 25);
System.out.println("Name: " + user.getName());
System.out.println("Age: " + user.getAge());
}
}

Python 模块创建

# myapp/model/user.py
class User:
def __init__(self, name, age):
self.name = name
self.age = age

def get_name(self):
return self.name

def get_age(self):
return self.age

# myapp/main.py
from myapp.model.user import User

def main():
user = User("Alice", 25)
print(f"Name: {user.get_name()}")
print(f"Age: {user.get_age()}")

if __name__ == "__main__":
main()

对比

操作JavaPython
模块文件.java 文件.py 文件
类定义每个文件通常一个类一个文件可以多个类和函数
主入口main 方法if __name__ == "__main__"
导入方式包路径 + 类名模块路径 + 类/函数名

10.5 包的初始化

Java 包初始化

Java 没有专门的包初始化机制,通常在静态代码块中初始化静态变量。

Python 包初始化

Python 使用 __init__.py 文件进行包初始化。

Python __init__.py 示例

# myapp/__init__.py
"""MyApp package"""

__version__ = "1.0.0"
__author__ = "Alice"

# 从子模块导入常用类和函数
from .model.user import User
from .service.user_service import UserService

# 定义包级别的函数
def get_version():
return __version__

# 包导入时执行的代码
print(f"MyApp v{__version__} initialized")

使用方式

import myapp

print(myapp.__version__)
print(myapp.__author__)
print(myapp.get_version())

# 直接使用从 __init__.py 导入的类
user = myapp.User("Bob", 30)
print(user.get_name())

10.6 模块搜索路径

Java 类路径

  • Java 使用 CLASSPATH 环境变量和 -cp 参数指定类路径
  • 类加载器从类路径中查找类文件

Python 模块搜索路径

  • Python 使用 sys.path 列表指定模块搜索路径
  • 搜索顺序:当前目录 → PYTHONPATH 环境变量 → 标准库目录 → 第三方库目录

Python 模块搜索路径示例

import sys

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

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

# 导入自定义模块
import mymodule

10.7 相对导入

Java 相对导入

// 在 com.example.service 包中
package com.example.service;

// 相对导入(Java 7+)
import static com.example.model.User;
import static com.example.util.Validator;

Python 相对导入

# 在 myapp/service/user_service.py 中

# 相对导入
from ..model.user import User
from ..util.validator import validate

# 相对导入的不同级别
# . 表示当前包
# .. 表示父包
# ... 表示祖父包

class UserService:
def create_user(self, name, age):
validate(name, age)
return User(name, age)

对比

特性JavaPython
相对导入语法import static package.Classfrom ..module import member
导入级别基于包层次使用点号表示级别
适用范围同一包内同一包内的模块

10.8 第三方库管理

Java 依赖管理

  • Maven:使用 pom.xml 管理依赖
  • Gradle:使用 build.gradle 管理依赖
  • 依赖仓库:Maven Central, JCenter 等

Python 依赖管理

  • pip:Python 包安装工具
  • requirements.txt:记录依赖版本
  • Poetry:更现代的依赖管理工具
  • 依赖仓库:PyPI (Python Package Index)

对比

操作Java (Maven)Python (pip)
安装依赖mvn installpip install package
导出依赖mvn dependency:copy-dependenciespip freeze > requirements.txt
安装所有依赖mvn installpip install -r requirements.txt
依赖声明pom.xmlrequirements.txt
依赖仓库Maven CentralPyPI

Python 依赖管理示例

# 安装单个包
pip install requests

# 安装指定版本
pip install requests==2.28.0

# 升级包
pip install --upgrade requests

# 卸载包
pip uninstall requests

# 导出依赖
pip freeze > requirements.txt

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

10.9 标准库

Java 标准库

  • java.lang:核心类
  • java.util:工具类和集合
  • java.io:IO 操作
  • java.net:网络操作
  • java.math:数学运算
  • java.time:日期时间

Python 标准库

  • os:操作系统接口
  • sys:Python 解释器相关
  • math:数学函数
  • datetime:日期时间
  • collections:集合扩展
  • json:JSON 处理
  • re:正则表达式
  • urllib:URL 处理
  • socket:网络编程
  • threading:多线程
  • multiprocessing:多进程

对比

功能JavaPython
文件操作java.ioos, os.path
网络操作java.netsocket, urllib
日期时间java.timedatetime
正则表达式java.util.regexre
数学运算java.mathmath
集合操作java.utilcollections
JSON 处理javax.jsonjson

10.10 练习

  1. 模块创建练习:创建一个包含数学工具函数的模块
  2. 包创建练习:创建一个包含多个子模块的包
  3. 导入练习:练习不同的导入方式(导入整个模块、导入特定成员、使用别名)
  4. 相对导入练习:在包内使用相对导入
  5. 依赖管理练习:使用 pip 安装第三方库并创建 requirements.txt 文件
  6. 标准库练习:使用 Python 标准库完成一个小任务(如文件操作、日期处理)

10.11 小结

  • Python 的模块系统比 Java 更简单,一个 .py 文件就是一个模块
  • Python 的包通过 __init__.py 文件标识,而 Java 通过 package 声明
  • Python 的导入语法更灵活,支持别名和多种导入方式
  • Python 的相对导入使用点号表示级别,比 Java 更直观
  • Python 的依赖管理使用 pip,比 Maven/Gradle 更轻量级
  • Python 的标准库非常丰富,覆盖了大多数常见任务
  • Python 的 if __name__ == "__main__" 机制比 Java 的 main 方法更灵活

通过本章的学习,你已经了解了 Java 和 Python 在模块与包上的主要区别。接下来,我们将学习 Python 的高级特性。