Python疯狂练习60天——第九天

今日练习主题:模块、包和Python标准库

今天我们将学习Python的模块系统、包的创建和使用,以及Python标准库中一些常用模块的功能。

练习1:创建和使用自定义模块

# 先创建 math_utils.py 文件
"""
math_utils.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

def factorial(n):
    """计算阶乘"""
    if n < 0:
        raise ValueError("阶乘不能为负数")
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

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

# 模块测试代码
if __name__ == "__main__":
    print("测试数学工具模块:")
    print(f"5 + 3 = {add(5, 3)}")
    print(f"10 - 4 = {subtract(10, 4)}")
    print(f"6 * 7 = {multiply(6, 7)}")
    print(f"15 / 3 = {divide(15, 3)}")
    print(f"5! = {factorial(5)}")
    print(f"17是质数吗? {is_prime(17)}")
# 在另一个文件中使用自定义模块
# main.py
import math_utils as mu
from math_utils import is_prime

print("=== 使用自定义数学模块 ===")

# 使用模块中的函数
result = mu.add(10, 20)
print(f"10 + 20 = {result}")

result = mu.multiply(5, 6)
print(f"5 × 6 = {result}")

# 测试质数判断
numbers = [2, 3, 4, 5, 17, 21, 29]
print("
质数检测:")
for num in numbers:
    print(f"{num} 是质数: {is_prime(num)}")

# 测试异常处理
try:
    result = mu.divide(10, 0)
except ValueError as e:
    print(f"
错误: {e}")

# 查看模块信息
print(f"
模块名称: {mu.__name__}")
print(f"模块文档: {mu.__doc__}")

练习2:创建和使用包

# 创建包结构:
# my_package/
# │
# ├── __init__.py
# ├── string_utils.py
# ├── file_utils.py
# └── data_utils.py

# __init__.py 文件内容:
"""
my_package - 实用工具包
包含字符串处理、文件操作和数据工具
"""

from .string_utils import reverse_string, count_words
from .file_utils import read_file, write_file
from .data_utils import DataProcessor

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

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

def count_words(text):
    """统计文本中的单词数"""
    words = text.split()
    return len(words)

def to_title_case(text):
    """转换为标题格式"""
    return text.title()

# file_utils.py 文件内容:
import os

def read_file(filename):
    """读取文件内容"""
    if not os.path.exists(filename):
        raise FileNotFoundError(f"文件 {filename} 不存在")
    
    with open(filename, 'r', encoding='utf-8') as file:
        return file.read()

def write_file(filename, content):
    """写入文件内容"""
    with open(filename, 'w', encoding='utf-8') as file:
        file.write(content)

def file_exists(filename):
    """检查文件是否存在"""
    return os.path.exists(filename)

# data_utils.py 文件内容:
class DataProcessor:
    """数据处理类"""
    
    def __init__(self, data):
        self.data = data
    
    def get_stats(self):
        """获取数据统计信息"""
        if not self.data:
            return {}
        
        return {
            'count': len(self.data),
            'sum': sum(self.data),
            'average': sum(self.data) / len(self.data),
            'max': max(self.data),
            'min': min(self.data)
        }
    
    def filter_data(self, condition):
        """过滤数据"""
        return [x for x in self.data if condition(x)]
# 使用自定义包
from my_package import reverse_string, count_words, read_file, DataProcessor
import my_package as mp

print("=== 使用自定义包 ===")

# 使用字符串工具
text = "Hello World Python Programming"
print(f"原始文本: {text}")
print(f"反转文本: {reverse_string(text)}")
print(f"单词数量: {count_words(text)}")

# 使用数据处理
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
processor = DataProcessor(data)
stats = processor.get_stats()
print(f"
数据统计: {stats}")

# 过滤数据
even_numbers = processor.filter_data(lambda x: x % 2 == 0)
print(f"偶数: {even_numbers}")

# 查看包信息
print(f"
包版本: {mp.__version__}")
print(f"作者: {mp.__author__}")

练习3:os和sys模块

import os
import sys

print("=== os 和 sys 模块使用 ===")

# os模块示例
print(f"当前工作目录: {os.getcwd()}")
print(f"操作系统: {os.name}")
print(f"环境变量PATH: {os.getenv('PATH', '未找到')}")

# 文件和目录操作
current_dir = os.getcwd()
print(f"当前目录内容: {os.listdir(current_dir)}")

# 创建测试目录和文件
test_dir = "test_dir"
if not os.path.exists(test_dir):
    os.makedirs(test_dir)
    print(f"创建目录: {test_dir}")

test_file = os.path.join(test_dir, "test.txt")
with open(test_file, 'w') as f:
    f.write("Hello OS Module!")

print(f"文件大小: {os.path.getsize(test_file)} 字节")
print(f"是文件吗? {os.path.isfile(test_file)}")
print(f"是目录吗? {os.path.isdir(test_dir)}")

# sys模块示例
print(f"
Python版本: {sys.version}")
print(f"平台: {sys.platform}")
print(f"命令行参数: {sys.argv}")
print(f"默认编码: {sys.getdefaultencoding()}")

# 模块搜索路径
print("
模块搜索路径:")
for path in sys.path:
    print(f"  {path}")

# 清理
import shutil
shutil.rmtree(test_dir)
print(f"
已清理测试目录: {test_dir}")

练习4:datetime和time模块

import datetime
import time

print("=== datetime 和 time 模块使用 ===")

# datetime模块
now = datetime.datetime.now()
print(f"当前时间: {now}")
print(f"日期: {now.date()}")
print(f"时间: {now.time()}")
print(f"年份: {now.year}, 月份: {now.month}, 日: {now.day}")

# 时间计算
tomorrow = now + datetime.timedelta(days=1)
last_week = now - datetime.timedelta(weeks=1)
print(f"明天: {tomorrow}")
print(f"上周: {last_week}")

# 时间格式化
formatted = now.strftime("%Y-%m-%d %H:%M:%S")
print(f"格式化时间: {formatted}")

# 解析时间字符串
time_str = "2024-01-15 14:30:00"
parsed_time = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
print(f"解析的时间: {parsed_time}")

# time模块
print(f"
当前时间戳: {time.time()}")
print(f"可读时间: {time.ctime()}")

# 计时功能
start_time = time.time()
time.sleep(2)  # 休眠2秒
end_time = time.time()
print(f"程序运行时间: {end_time - start_time:.2f} 秒")

# 性能计时
start = time.perf_counter()
sum(range(1000000))
end = time.perf_counter()
print(f"计算耗时: {end - start:.6f} 秒")

练习5:random和json模块

import random
import json

print("=== random 和 json 模块使用 ===")

# random模块
print("随机数示例:")
print(f"随机整数(1-100): {random.randint(1, 100)}")
print(f"随机浮点数: {random.random():.3f}")
print(f"随机选择: {random.choice(['苹果', '香蕉', '橙子', '葡萄'])}")

# 随机抽样
numbers = list(range(1, 11))
random.shuffle(numbers)
print(f"打乱列表: {numbers}")
print(f"随机样本: {random.sample(numbers, 3)}")

# 生成随机数据
random_data = [random.randint(1, 100) for _ in range(5)]
print(f"随机数据列表: {random_data}")

# json模块
print("
JSON操作示例:")

# Python对象转换为JSON
data = {
    "name": "张三",
    "age": 25,
    "is_student": False,
    "courses": ["数学", "英语", "编程"],
    "scores": {"数学": 90, "英语": 85, "编程": 95}
}

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

# JSON转换为Python对象
parsed_data = json.loads(json_str)
print("
解析后的Python对象:")
print(f"姓名: {parsed_data['name']}")
print(f"年龄: {parsed_data['age']}")
print(f"课程: {', '.join(parsed_data['courses'])}")

# 文件读写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(f"
从文件加载的数据: {loaded_data['name']}")

# 清理
import os
if os.path.exists('data.json'):
    os.remove('data.json')

练习6:collections和itertools模块

from collections import Counter, defaultdict, deque
import itertools

print("=== collections 和 itertools 模块使用 ===")

# collections.Counter
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
word_count = Counter(words)
print(f"单词计数: {word_count}")
print(f"最常见的2个: {word_count.most_common(2)}")

# collections.defaultdict
student_grades = defaultdict(list)
student_grades["张三"].append(90)
student_grades["李四"].append(85)
student_grades["张三"].append(95)
print(f"学生成绩: {dict(student_grades)}")

# collections.deque (双端队列)
queue = deque([1, 2, 3])
queue.append(4)      # 右边添加
queue.appendleft(0)  # 左边添加
print(f"队列: {queue}")
print(f"弹出左边: {queue.popleft()}")
print(f"弹出右边: {queue.pop()}")

# itertools
print("
itertools示例:")
# 无限迭代器
counter = itertools.count(start=10, step=2)
print(f"计数器前5个: {[next(counter) for _ in range(5)]}")

# 排列组合
letters = ['A', 'B', 'C']
print(f"排列: {list(itertools.permutations(letters, 2))}")
print(f"组合: {list(itertools.combinations(letters, 2))}")

# 链式迭代
chained = list(itertools.chain([1, 2, 3], [4, 5, 6]))
print(f"链式迭代: {chained}")

# 分组
data = [1, 1, 2, 2, 3, 3, 3]
grouped = {k: list(v) for k, v in itertools.groupby(data)}
print(f"分组: {grouped}")

练习7:re模块(正则表达式)

import re

print("=== re 模块使用(正则表达式)===")

text = """
我的电话号码是: 138-1234-5678
公司电话: 010-8888-9999
紧急联系: 120
邮箱: example@email.com
另一个邮箱: test.user@domain.cn
网址: https://www.example.com
IP地址: 192.168.1.1
日期: 2024-01-15
"""

# 匹配电话号码
phone_pattern = r'd{3}-d{4}-d{4}'
phones = re.findall(phone_pattern, text)
print(f"找到的电话号码: {phones}")

# 匹配邮箱
email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}'
emails = re.findall(email_pattern, text)
print(f"找到的邮箱: {emails}")

# 匹配URL
url_pattern = r'https?://[a-zA-Z0-9.-]+.[a-zA-Z]{2,}'
urls = re.findall(url_pattern, text)
print(f"找到的URL: {urls}")

# 替换操作
new_text = re.sub(r'd{3}-d{4}-d{4}', '***-****-****', text)
print("
替换电话号码后的文本:")
print(new_text)

# 分割操作
sample_text = "apple,banana;orange grape"
items = re.split(r'[,; ]', sample_text)
print(f"分割结果: {items}")

# 搜索和匹配
match = re.search(r'日期: (d{4}-d{2}-d{2})', text)
if match:
    print(f"找到日期: {match.group(1)}")

# 验证字符串
def is_valid_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

test_emails = ["test@example.com", "invalid.email", "user@domain"]
for email in test_emails:
    print(f"{email} 是有效邮箱吗? {is_valid_email(email)}")

今日挑战:

创建一个完整的项目结构,包含多个模块和包,实现一个简单的任务管理系统。

# 项目结构:
# task_manager/
# │
# ├── __init__.py
# ├── main.py
# ├── models/
# │   ├── __init__.py
# │   ├── task.py
# │   └── user.py
# ├── utils/
# │   ├── __init__.py
# │   ├── file_utils.py
# │   └── date_utils.py
# └── data/
#     └── tasks.json

# models/task.py
import json
from datetime import datetime
from enum import Enum

class Priority(Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3

class Status(Enum):
    PENDING = "待完成"
    IN_PROGRESS = "进行中"
    COMPLETED = "已完成"

class Task:
    def __init__(self, title, description, priority=Priority.MEDIUM, due_date=None):
        self.title = title
        self.description = description
        self.priority = priority
        self.status = Status.PENDING
        self.created_at = datetime.now()
        self.due_date = due_date
        self.completed_at = None
    
    def mark_completed(self):
        self.status = Status.COMPLETED
        self.completed_at = datetime.now()
    
    def to_dict(self):
        return {
            'title': self.title,
            'description': self.description,
            'priority': self.priority.value,
            'status': self.status.value,
            'created_at': self.created_at.isoformat(),
            'due_date': self.due_date.isoformat() if self.due_date else None,
            'completed_at': self.completed_at.isoformat() if self.completed_at else None
        }
    
    @classmethod
    def from_dict(cls, data):
        task = cls(data['title'], data['description'])
        task.priority = Priority(data['priority'])
        task.status = Status(data['status'])
        task.created_at = datetime.fromisoformat(data['created_at'])
        task.due_date = datetime.fromisoformat(data['due_date']) if data['due_date'] else None
        task.completed_at = datetime.fromisoformat(data['completed_at']) if data['completed_at'] else None
        return task

# utils/file_utils.py
import json
import os

def save_tasks(tasks, filename='data/tasks.json'):
    """保存任务到JSON文件"""
    os.makedirs(os.path.dirname(filename), exist_ok=True)
    with open(filename, 'w', encoding='utf-8') as f:
        json.dump([task.to_dict() for task in tasks], f, ensure_ascii=False, indent=2)

def load_tasks(filename='data/tasks.json'):
    """从JSON文件加载任务"""
    if not os.path.exists(filename):
        return []
    
    with open(filename, 'r', encoding='utf-8') as f:
        data = json.load(f)
        return [Task.from_dict(task_data) for task_data in data]

# utils/date_utils.py
from datetime import datetime, timedelta

def get_current_time():
    """获取当前时间"""
    return datetime.now()

def format_date(date, format_str="%Y-%m-%d %H:%M"):
    """格式化日期"""
    if date:
        return date.strftime(format_str)
    return "未设置"

def parse_date(date_str, format_str="%Y-%m-%d"):
    """解析日期字符串"""
    try:
        return datetime.strptime(date_str, format_str)
    except ValueError:
        return None

# main.py
from models.task import Task, Priority, Status
from utils.file_utils import save_tasks, load_tasks
from utils.date_utils import format_date, parse_date
import sys

class TaskManager:
    def __init__(self):
        self.tasks = load_tasks()
    
    def add_task(self, title, description, priority=Priority.MEDIUM, due_date=None):
        """添加新任务"""
        task = Task(title, description, priority, due_date)
        self.tasks.append(task)
        save_tasks(self.tasks)
        print(f"任务 '{title}' 添加成功!")
    
    def list_tasks(self, filter_status=None):
        """列出任务"""
        if not self.tasks:
            print("没有任务")
            return
        
        filtered_tasks = self.tasks
        if filter_status:
            filtered_tasks = [t for t in self.tasks if t.status == filter_status]
        
        print(f"
{'='*60}")
        print(f"{'任务列表':^60}")
        print(f"{'='*60}")
        
        for i, task in enumerate(filtered_tasks, 1):
            print(f"{i}. {task.title}")
            print(f"   描述: {task.description}")
            print(f"   优先级: {task.priority.name}")
            print(f"   状态: {task.status.value}")
            print(f"   创建时间: {format_date(task.created_at)}")
            if task.due_date:
                print(f"   截止时间: {format_date(task.due_date)}")
            if task.completed_at:
                print(f"   完成时间: {format_date(task.completed_at)}")
            print(f"   {'-'*40}")
    
    def complete_task(self, task_index):
        """标记任务完成"""
        if 0 <= task_index < len(self.tasks):
            task = self.tasks[task_index]
            if task.status != Status.COMPLETED:
                task.mark_completed()
                save_tasks(self.tasks)
                print(f"任务 '{task.title}' 已完成!")
            else:
                print("任务已经是完成状态")
        else:
            print("无效的任务索引")
    
    def run(self):
        """运行任务管理器"""
        print("=== 任务管理系统 ===")
        
        while True:
            print("
请选择操作:")
            print("1. 添加任务")
            print("2. 查看所有任务")
            print("3. 查看待完成任务")
            print("4. 标记任务完成")
            print("5. 退出")
            
            choice = input("请输入选项 (1-5): ")
            
            if choice == "1":
                title = input("任务标题: ")
                description = input("任务描述: ")
                priority = input("优先级 (LOW/MEDIUM/HIGH, 默认为MEDIUM): ").upper()
                due_date_str = input("截止日期 (YYYY-MM-DD, 可选): ")
                
                priority_map = {"LOW": Priority.LOW, "MEDIUM": Priority.MEDIUM, "HIGH": Priority.HIGH}
                priority = priority_map.get(priority, Priority.MEDIUM)
                due_date = parse_date(due_date_str) if due_date_str else None
                
                self.add_task(title, description, priority, due_date)
            
            elif choice == "2":
                self.list_tasks()
            
            elif choice == "3":
                self.list_tasks(Status.PENDING)
            
            elif choice == "4":
                self.list_tasks(Status.PENDING)
                if any(task.status == Status.PENDING for task in self.tasks):
                    try:
                        task_num = int(input("请输入要完成的任务编号: ")) - 1
                        self.complete_task(task_num)
                    except ValueError:
                        print("请输入有效的数字")
            
            elif choice == "5":
                print("感谢使用任务管理系统!")
                break
            
            else:
                print("无效选项,请重新选择")

if __name__ == "__main__":
    manager = TaskManager()
    manager.run()

学习提示:

  1. 模块:单个Python文件,包含可重用的代码
  2. :包含多个模块的目录,必须有 __init__.py 文件
  3. 标准库:Python自带的丰富模块集合
  4. import语句:导入模块或特定功能
  5. if __name__ == “__main__”:模块测试代码
  6. 相对导入:在包内使用 . 导入相对路径的模块

明天我们将学习错误处理和调试技巧!坚持练习,你的代码组织能力会越来越强!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 共1条

请登录后发表评论