Python模块与包

学习目标

通过本集的学习,你将能够:

  • 理解什么是模块
  • 学会导入和使用模块
  • 创建自己的模块
  • 理解包的概念
  • 使用Python标准库

1. 什么是模块?

模块就是一个包含Python代码的文件,文件扩展名是.py

1.1 为什么需要模块?

没有模块时:
┌─────────────────────────────────────┐
│    一个巨大的文件,10000行代码       │
│    难以维护、难以复用                 │
└─────────────────────────────────────┘

有模块时:
┌─────────┐  ┌─────────┐  ┌─────────┐
│ utils.py│  │ math.py │  │ io.py   │
│  (工具) │  │ (数学)  │  │ (输入输出)│
└────┬────┘  └────┬────┘  └────┬────┘
     │             │             │
     └─────────────┼─────────────┘
                   ▼
           ┌───────────────┐
           │   主程序      │
           └───────────────┘

2. 导入模块

2.1 基本导入

# 导入整个模块
import math

print(math.pi)           # 圆周率: 3.14159...
print(math.sqrt(16))     # 平方根: 4.0
print(math.sin(math.pi/2))  # 正弦: 1.0

2.2 导入特定内容

# 只导入需要的函数或变量
from math import pi, sqrt

print(pi)       # 直接使用,不需要math.
print(sqrt(25)) # 5.0

2.3 导入并改名

# 给模块改名
import math as m

print(m.pi)
print(m.sqrt(9))

# 给函数改名
from math import sqrt as square_root

print(square_root(16))  # 4.0

2.4 导入所有内容(不推荐)

# 导入模块中的所有内容(不推荐,可能造成命名冲突)
from math import *

print(pi)
print(sin(0))

3. 创建自己的模块

3.1 简单的模块示例

创建一个文件 my_module.py

# my_module.py

# 变量
greeting = "Hello, World!"

# 函数
def add(a, b):
    return a + b

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

# 类
class Calculator:
    def __init__(self):
        self.result = 0
    
    def add(self, value):
        self.result += value
        return self.result
    
    def reset(self):
        self.result = 0

3.2 使用自定义模块

创建另一个文件 main.py

# main.py

# 导入自定义模块
import my_module

# 使用模块中的变量
print(my_module.greeting)  # Hello, World!

# 使用模块中的函数
print(my_module.add(3, 5))      # 8
print(my_module.multiply(3, 5))  # 15

# 使用模块中的类
calc = my_module.Calculator()
print(calc.add(10))  # 10
print(calc.add(5))   # 15
calc.reset()
print(calc.add(3))   # 3

3.3 模块的 __name__ 属性

# my_module.py

def hello():
    print("Hello!")

# 只有当直接运行这个文件时才执行
if __name__ == "__main__":
    print("这是模块的主程序")
    hello()

4. 包(Package)

包是一个包含多个模块的文件夹,文件夹中必须有一个 __init__.py 文件。

4.1 包的结构

my_package/
├── __init__.py
├── math_utils.py
├── string_utils.py
└── io_utils.py

4.2 创建包

创建 my_package/__init__.py

# my_package/__init__.py

# 可以在这里初始化包
print("My package is being imported!")

# 也可以导入一些内容,方便用户使用
from .math_utils import add, multiply
from .string_utils import to_uppercase

创建 my_package/math_utils.py

# my_package/math_utils.py

def add(a, b):
    return a + b

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

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

创建 my_package/string_utils.py

# my_package/string_utils.py

def to_uppercase(s):
    return s.upper()

def to_lowercase(s):
    return s.lower()

def reverse_string(s):
    return s[::-1]

4.3 使用包

# 使用包
import my_package

print(my_package.add(3, 5))           # 8
print(my_package.to_uppercase("hello")) # HELLO

# 或者从包中导入特定模块
from my_package import math_utils
print(math_utils.divide(10, 2))  # 5.0

# 或者从包中导入特定函数
from my_package.math_utils import multiply
print(multiply(4, 5))  # 20

5. Python标准库

Python自带了很多有用的模块,这就是标准库。

5.1 常用标准库模块

# os:操作系统相关
import os
print(os.getcwd())          # 获取当前工作目录
print(os.listdir('.'))       # 列出目录内容

# sys:系统相关
import sys
print(sys.version)           # Python版本
print(sys.path)              # 模块搜索路径

# datetime:日期时间
from datetime import datetime, date
now = datetime.now()
print(now)                   # 当前日期时间
print(date.today())          # 今天的日期

# random:随机数
import random
print(random.random())        # 0到1之间的随机数
print(random.randint(1, 10)) # 1到10之间的随机整数

# json:JSON处理
import json
data = {"name": "Alice", "age": 20}
json_str = json.dumps(data)
print(json_str)  # '{"name": "Alice", "age": 20}'

# re:正则表达式(我们之前学过)
import re
result = re.search(r'\d+', 'abc123def')
print(result.group())  # '123'

6. 模块搜索路径

Python会在以下位置查找模块:

import sys
print(sys.path)

输出类似:

[
    '',                              # 当前目录
    '/usr/lib/python3.8',           # 标准库目录
    '/usr/local/lib/python3.8/site-packages'  # 第三方库目录
]

7. 实用案例

7.1 案例1:工具模块

创建 utils.py

# utils.py

def is_even(n):
    return n % 2 == 0

def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def fibonacci(n):
    sequence = []
    a, b = 0, 1
    for _ in range(n):
        sequence.append(a)
        a, b = b, a + b
    return sequence

if __name__ == "__main__":
    print("Testing utils module:")
    print("is_even(4):", is_even(4))
    print("is_prime(7):", is_prime(7))
    print("fibonacci(10):", fibonacci(10))

使用这个模块:

# use_utils.py
import utils

print(utils.is_even(10))        # True
print(utils.is_prime(17))        # True
print(utils.fibonacci(5))        # [0, 1, 1, 2, 3]

7.2 案例2:配置模块

创建 config.py

# config.py

# 数据库配置
DATABASE = {
    'host': 'localhost',
    'port': 5432,
    'name': 'mydb',
    'user': 'admin'
}

# API配置
API = {
    'url': 'https://api.example.com',
    'timeout': 30,
    'retries': 3
}

# 日志配置
LOGGING = {
    'level': 'INFO',
    'file': 'app.log'
}

def get_database_url():
    return f"postgresql://{DATABASE['user']}@{DATABASE['host']}:{DATABASE['port']}/{DATABASE['name']}"

使用配置模块:

# use_config.py
import config

print("Database host:", config.DATABASE['host'])
print("API URL:", config.API['url'])
print("Database URL:", config.get_database_url())

8. 自测问题

  1. 什么是模块?
  2. 如何导入模块?
  3. 什么是包?包和模块有什么区别?
  4. __init__.py 文件的作用是什么?
  5. 什么是Python标准库?

9. 下集预告

下一集我们将学习编程语言的语法!

参考资料

« 上一篇 Python异常处理 下一篇 » 理解编程语言的语法