← 返回首页 | ← 返回教程列表

Python学习教程 - 第六课:模块和包,代码的组织大师!

欢迎回来!🎉 这节课我们要学习如何组织代码——模块(Module)和包(Package),让我们的项目更有条理!


复习一下前五节课

前五节课我们学会了: - 变量和基本数据类型 - 条件判断和循环 - 列表和字典 - 函数(代码的魔法师) - 文件操作(数据持久化)

这节课我们要学习如何把代码组织得更好,以及如何使用别人写好的库!


第一个知识点:什么是模块?

模块就是一个 .py 文件,里面包含了相关的函数、类和变量。

为什么要用模块?

代码复用:同一个文件可以在多个项目中使用
组织代码:把相关功能放在一起
避免命名冲突:不同模块可以有同名函数
便于维护:修改一个模块不影响其他代码


第二个知识点:导入模块

基本导入

# 导入整个模块
import math

print(math.pi)           # 圆周率
print(math.sqrt(16))     # 平方根
print(math.sin(math.pi/2)) # 正弦函数

导入特定内容

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

print(pi)
print(sqrt(25))

导入并重命名

# 给模块起别名
import math as m

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

# 给函数起别名
from math import sqrt as square_root

print(square_root(16))

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

# 导入模块中的所有内容(可能导致命名冲突)
from math import *

print(pi)
print(sqrt(4))

第三个知识点:创建自己的模块

让我们创建一个实用的工具模块!

步骤1:创建 my_tools.py

# my_tools.py - 我的工具模块

def greet(name):
    """问候函数"""
    return f"你好,{name}!"

def add(a, b):
    """加法函数"""
    return a + b

def multiply(a, b):
    """乘法函数"""
    return a * b

def calculate_area(radius):
    """计算圆的面积"""
    import math
    return math.pi * radius ** 2

# 模块级别的变量
AUTHOR = "Python学习者"
VERSION = "1.0"

步骤2:在另一个文件中使用

# main.py - 主程序

import my_tools

# 使用模块中的函数
print(my_tools.greet("小明"))
print(f"3 + 5 = {my_tools.add(3, 5)}")
print(f"4 * 6 = {my_tools.multiply(4, 6)}")
print(f"半径为5的圆面积:{my_tools.calculate_area(5):.2f}")

# 使用模块中的变量
print(f"\n作者:{my_tools.AUTHOR}")
print(f"版本:{my_tools.VERSION}")

第四个知识点:__name____main__

让模块既可以被导入,也可以直接运行

# my_tools.py(改进版)

def greet(name):
    return f"你好,{name}!"

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

# 测试代码
if __name__ == "__main__":
    # 只有直接运行这个文件时才会执行
    print("这是my_tools模块的测试代码")
    print(greet("测试"))
    print(f"1 + 2 = {add(1, 2)}")

原理说明: - 当直接运行文件时,__name__ 的值是 "__main__" - 当被导入时,__name__ 的值是模块名("my_tools"


第五个知识点:什么是包?

就是一个文件夹,里面包含多个模块和一个特殊的 __init__.py 文件。

包的目录结构

my_package/
├── __init__.py      # 必须有标识这是一个包
├── module1.py       # 模块1
├── module2.py       # 模块2
└── subpackage/      # 子包
    ├── __init__.py
    └── module3.py

创建一个简单的包

# 创建目录结构
# my_math/
#   __init__.py
#   basic.py
#   advanced.py

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

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

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

def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

# advanced.py
import math

def square_root(x):
    return math.sqrt(x)

def power(base, exponent):
    return math.pow(base, exponent)

def factorial(n):
    if n < 0:
        raise ValueError("负数没有阶乘")
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

# __init__.py
from .basic import add, subtract, multiply, divide
from .advanced import square_root, power, factorial

__all__ = ['add', 'subtract', 'multiply', 'divide', 
           'square_root', 'power', 'factorial']

使用包

# 方式1:导入整个包
import my_math

print(my_math.add(3, 5))
print(my_math.factorial(5))

# 方式2:从包中导入特定内容
from my_math import add, factorial

print(add(10, 20))
print(factorial(10))

# 方式3:导入子模块
from my_math import basic

print(basic.multiply(4, 5))

第六个知识点:常用的标准库

Python自带了很多强大的标准库!

1. sys:系统相关

import sys

print("Python版本:", sys.version)
print("操作系统平台:", sys.platform)
print("命令行参数:", sys.argv)
print("模块搜索路径:", sys.path)

# 退出程序
# sys.exit(0)

2. os:操作系统接口

import os

print("当前工作目录:", os.getcwd())
print("环境变量:", os.environ.get("PATH"))

# 列出目录内容
print("目录内容:", os.listdir("."))

# 路径操作
print("路径拼接:", os.path.join("folder", "file.txt"))
print("是否存在:", os.path.exists("test.txt"))
print("是否是文件:", os.path.isfile("test.txt"))
print("是否是目录:", os.path.isdir("."))

3. datetime:日期和时间

from datetime import datetime, date, timedelta

# 当前时间
now = datetime.now()
print("当前时间:", now)
print("年:", now.year)
print("月:", now.month)
print("日:", now.day)
print("时:", now.hour)
print("分:", now.minute)
print("秒:", now.second)

# 格式化输出
print("格式化:", now.strftime("%Y-%m-%d %H:%M:%S"))

# 日期计算
today = date.today()
tomorrow = today + timedelta(days=1)
yesterday = today - timedelta(days=1)
print("今天:", today)
print("明天:", tomorrow)
print("昨天:", yesterday)

# 字符串转日期
date_str = "2024-01-15"
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
print("字符串转日期:", date_obj)

4. random:随机数

import random

# 随机整数
print("随机整数(0-9):", random.randint(0, 9))

# 随机浮点数
print("随机浮点数(0-1):", random.random())
print("随机浮点数(1-10):", random.uniform(1, 10))

# 随机选择
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print("随机选择:", random.choice(fruits))

# 随机打乱
random.shuffle(fruits)
print("打乱后:", fruits)

# 随机抽样
print("随机抽取2个:", random.sample(fruits, 2))

5. json:JSON处理

import json

# Python对象转JSON
data = {
    "name": "小明",
    "age": 18,
    "hobbies": ["读书", "游泳"]
}

json_str = json.dumps(data, ensure_ascii=False, indent=2)
print("JSON字符串:", json_str)

# JSON转Python对象
python_obj = json.loads(json_str)
print("Python对象:", python_obj)

# 读写JSON文件
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

with open("data.json", "r", encoding="utf-8") as f:
    loaded_data = json.load(f)
    print("从文件读取:", loaded_data)

6. re:正则表达式

import re

# 查找匹配
text = "我的电话是13812345678,邮箱是test@example.com"

# 查找手机号
phone_pattern = r"1[3-9]\d{9}"
phones = re.findall(phone_pattern, text)
print("手机号:", phones)

# 查找邮箱
email_pattern = r"\w+@\w+\.\w+"
emails = re.findall(email_pattern, text)
print("邮箱:", emails)

# 替换
new_text = re.sub(phone_pattern, "***", text)
print("替换后:", new_text)

# 验证
def is_valid_phone(phone):
    pattern = r"^1[3-9]\d{9}$"
    return re.match(pattern, phone) is not None

print("13812345678有效吗?", is_valid_phone("13812345678"))
print("123456789有效吗?", is_valid_phone("123456789"))

第七个知识点:安装和使用第三方库

使用pip安装

# 安装包
pip install requests

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

# 升级包
pip install --upgrade requests

# 卸载包
pip uninstall requests

# 查看已安装的包
pip list

# 查看包信息
pip show requests

常用的第三方库

1. requests:HTTP请求

import requests

# GET请求
response = requests.get("https://api.github.com")
print("状态码:", response.status_code)
print("响应内容:", response.json())

# POST请求
data = {"key": "value"}
response = requests.post("https://httpbin.org/post", json=data)
print(response.json())

2. pandas:数据分析

import pandas as pd

# 创建DataFrame
data = {
    "姓名": ["小明", "小红", "小刚"],
    "年龄": [18, 17, 19],
    "成绩": [90, 85, 95]
}

df = pd.DataFrame(data)
print(df)

# 读取CSV
# df = pd.read_csv("data.csv")

# 基本统计
print("\n统计信息:")
print(df.describe())

# 筛选
print("\n成绩大于90的:")
print(df[df["成绩"] > 90])

综合练习:实用工具包

让我们创建一个完整的工具包!

# 创建目录结构
# utils/
#   __init__.py
#   string_utils.py
#   math_utils.py
#   file_utils.py
#   date_utils.py

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

def count_words(s):
    """统计单词数"""
    return len(s.split())

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

def capitalize_sentences(s):
    """首字母大写"""
    sentences = s.split('. ')
    return '. '.join(sentence.capitalize() for sentence in sentences)

# math_utils.py
def is_prime(n):
    """判断是否是质数"""
    if n <= 1:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def fibonacci(n):
    """生成斐波那契数列"""
    fib = []
    a, b = 0, 1
    for _ in range(n):
        fib.append(b)
        a, b = b, a + b
    return fib

def gcd(a, b):
    """最大公约数"""
    while b:
        a, b = b, a % b
    return a

def lcm(a, b):
    """最小公倍数"""
    return a * b // gcd(a, b)

# file_utils.py
import os

def get_file_extension(filename):
    """获取文件扩展名"""
    return os.path.splitext(filename)[1]

def read_file_lines(filename):
    """读取文件所有行"""
    with open(filename, 'r', encoding='utf-8') as f:
        return f.readlines()

def count_file_lines(filename):
    """统计文件行数"""
    with open(filename, 'r', encoding='utf-8') as f:
        return sum(1 for _ in f)

def find_files_by_extension(directory, extension):
    """查找指定扩展名的文件"""
    found = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith(extension):
                found.append(os.path.join(root, file))
    return found

# date_utils.py
from datetime import datetime, date

def get_age(birthdate):
    """计算年龄"""
    today = date.today()
    return today.year - birthdate.year - ((today.month, today.day) < (birthdate.month, birthdate.day))

def is_leap_year(year):
    """判断是否是闰年"""
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

def days_until(target_date):
    """计算到目标日期的天数"""
    today = date.today()
    delta = target_date - today
    return delta.days

def format_date(date_obj, format="%Y-%m-%d"):
    """格式化日期"""
    return date_obj.strftime(format)

# __init__.py
from .string_utils import reverse_string, count_words, is_palindrome, capitalize_sentences
from .math_utils import is_prime, fibonacci, gcd, lcm
from .file_utils import get_file_extension, read_file_lines, count_file_lines, find_files_by_extension
from .date_utils import get_age, is_leap_year, days_until, format_date

__version__ = "1.0.0"
__author__ = "Python学习者"

# 使用这个工具包
import utils

# 测试字符串工具
print("反转字符串:", utils.reverse_string("Hello"))
print("是回文吗?", utils.is_palindrome("A man a plan a canal Panama"))

# 测试数学工具
print("是质数吗?", utils.is_prime(17))
print("斐波那契数列:", utils.fibonacci(10))

# 测试日期工具
from datetime import date
birthdate = date(2000, 5, 15)
print("年龄:", utils.get_age(birthdate))
print("2024是闰年吗?", utils.is_leap_year(2024))

第六课小结

今天我们学会了:

模块:单个.py文件,包含函数和变量
导入模块:import、from...import、as
创建模块:自己写.py文件
:包含多个模块的文件夹
标准库:sys、os、datetime、random、json、re
第三方库:使用pip安装,requests、pandas等
name:判断是直接运行还是被导入


课后练习 ✏️

  1. 创建一个工具模块,包含字符串处理、数学计算等函数
  2. 创建一个包,包含多个相关模块
  3. 使用datetime模块编写一个生日提醒程序
  4. 使用random模块编写一个猜数字游戏
  5. 使用requests模块调用一个公开API并处理返回数据

下节课预告:我们会学习面向对象编程(OOP),这是Python编程的重要范式!

继续加油!你已经掌握了Python编程的核心技能!💪