零基础学 Python——模块和包

亲爱的亦菲彦祖们,欢迎回到我们的编程学习系列!在前面的学习中,我们已经掌握了类与对象的基本概念以及面向对象编程的核心特性。今天,我们将深入探讨模块和包,这是Python编程中组织和复用代码的重要工具。通过理解模块和包的概念及其使用方法,您将能够编写更加清晰、可维护和高效的代码。让我们一起来开启这段充满实用知识的学习之旅吧!

一、模块和包

1. 目标

通过本节学习,您将能够:

  • 了解模块的基本概念及其重要性
  • 掌握导入模块的多种方式
  • 学会如何创建和使用自定义模块
  • 理解包的概念及其使用方法

2. 模块

2.1 模块简介

**模块(Module)**是一个包含Python定义和语句的文件,文件名以.py结尾。模块可以定义函数、类和变量,也可以包含可执行的代码。通过模块化,您可以将相关的功能组织在一起,实现代码的复用和管理。

示例

# math_module.py

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

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

2.2 导入模块

Python提供了多种方式来导入模块,以满足不同的需求。

2.2.1 导入模块的方式

主要的导入模块方式包括:

  1. import 模块名
  2. from 模块名 import 功能名
  3. from 模块名 import *
  4. import 模块名 as 别名
  5. from 模块名 import 功能名 as 别名
2.2.2 导入方式详解
2.2.2.1 import语句

语法

# 导入单个模块
import 模块名

# 导入多个模块
import 模块名1, 模块名2, ...

使用

通过模块名调用其功能。

示例

import math

print(math.sqrt(16))  # 输出:4.0

解释

  • import math导入了Python的内置math模块。
  • 使用math.sqrt()调用模块中的sqrt函数。

2.2.2.2 from...import...语句

语法

from 模块名 import 功能1, 功能2, ...

使用

直接使用导入的功能,无需模块名作为前缀。

示例

from math import sqrt, ceil

print(sqrt(25))  # 输出:5.0
print(ceil(4.2))  # 输出:5

解释

  • from math import sqrt, ceilmath模块中导入sqrtceil函数。
  • 直接调用sqrt()ceil(),无需前缀math.

2.2.2.3 from...import *语句

语法

from 模块名 import *

使用

导入模块中的所有公共功能。

示例

from math import *

print(sin(0))    # 输出:0.0
print(pi)        # 输出:3.141592653589793

注意

  • 使用*导入所有内容可能导致命名冲突,建议谨慎使用。
  • 明确导入需要的功能,可以提高代码的可读性和安全性。

2.2.2.4 使用as定义别名

语法

# 为模块定义别名
import 模块名 as 别名

# 为功能定义别名
from 模块名 import 功能 as 别名

使用

使用别名来简化代码书写或避免命名冲突。

示例

# 模块别名
import math as mt

print(mt.sqrt(9))  # 输出:3.0

# 功能别名
from math import factorial as fact

print(fact(5))  # 输出:120

解释

  • import math as mtmath模块重命名为mt
  • from math import factorial as factfactorial函数重命名为fact

2.3 制作模块

在Python中,每个Python文件都可以作为一个模块。自定义模块名必须符合标识符命名规则(即只能包含字母、数字和下划线,且不能以数字开头)。

2.3.1 定义模块

步骤

  1. 创建一个新的Python文件,例如my_module1.py
  2. 在文件中定义函数、类或变量。

示例

# my_module1.py

def testA(a, b):
    print(a + b)

2.3.2 测试模块

为了确保模块正常工作,可以在模块文件中添加测试代码。为了防止模块被导入时自动执行测试代码,可以使用if __name__ == '__main__':判断。

示例

# my_module1.py

def testA(a, b):
    print(a + b)

if __name__ == '__main__':
    testA(1, 1)  # 仅在模块被直接运行时执行

解释

  • my_module1.py被直接运行时,会执行testA(1, 1),输出2
  • my_module1被导入到其他模块时,不会执行testA(1, 1),避免不必要的输出。

2.3.3 调用模块

通过导入自定义模块,可以在其他Python文件中调用其功能。

示例

# main.py

import my_module1

my_module1.testA(5, 7)  # 输出:12

解释

  • import my_module1导入了自定义模块。
  • 使用my_module1.testA(5, 7)调用模块中的testA函数。

2.4 模块定位顺序

当导入一个模块时,Python解释器会按照以下顺序搜索模块的位置:

  1. 当前目录:首先在当前执行脚本的目录中查找模块。
  2. 环境变量PYTHONPATH:如果在当前目录未找到,Python会搜索环境变量PYTHONPATH中指定的目录。
  3. 默认路径:如果仍未找到,Python会搜索安装过程确定的默认目录(如/usr/local/lib/python/)。

查看模块搜索路径

模块搜索路径存储在sys.path变量中。可以通过以下代码查看:

import sys

print(sys.path)

注意

  • 确保自定义模块名不与Python内置模块或已安装的第三方模块名冲突,以避免导入错误的模块。
  • 如果自定义模块位于非标准路径,可以通过修改sys.path或设置PYTHONPATH环境变量来包含该路径。

3. 包

**包(Package)**是一个包含多个相关模块的文件夹。包通过在文件夹内添加一个特殊的__init__.py文件来标识,__init__.py文件可以是空的,也可以包含包的初始化代码。

3.1 制作包

步骤

  1. 创建一个新的文件夹,例如mypackage
  2. mypackage文件夹内创建一个空的__init__.py文件。
  3. 在包内添加相关的模块文件,例如my_module1.pymy_module2.py

示例

mypackage/
├── __init__.py
├── my_module1.py
└── my_module2.py

模块内容

# my_module1.py

print(1)

def info_print1():
    print('my_module1')
# my_module2.py

print(2)

def info_print2():
    print('my_module2')

解释

  • mypackage文件夹通过__init__.py文件被识别为一个包。
  • my_module1.pymy_module2.py是包内的两个模块,包含各自的功能。

3.2 导入包

包中的模块可以通过多种方式导入,以便在其他Python脚本中使用。

导入包的方式

  1. import 包名.模块名
  2. from 包名.模块名 import 函数名
3.2.1 体验导入包

示例

# main.py

"""方法1"""
import mypackage.my_module1
mypackage.my_module1.info_print1()

"""方法2"""
from mypackage.my_module2 import info_print2
info_print2()

运行结果

1
my_module1
2
my_module2

解释

  • import mypackage.my_module1导入了包mypackage中的模块my_module1,并调用其info_print1函数。
  • from mypackage.my_module2 import info_print2从包mypackage中的模块my_module2导入了info_print2函数,并直接调用。

3.3 拓展-封装学生信息管理系统成包

为了进一步实践模块和包的使用,我们可以将之前设计的学生信息管理系统封装成一个包。这样不仅可以更好地组织代码,还能方便地在不同项目中复用该系统。

步骤

  1. 创建一个新的包文件夹,例如student_management
  2. student_management文件夹内创建一个空的__init__.py文件。
  3. 将之前设计的Student类和StudentManager类分别放入不同的模块文件中,例如student.pymanager.py

项目结构

student_management/
├── __init__.py
├── student.py
└── manager.py

模块内容

# student.py

class Student:
    """学生信息类"""
    def __init__(self, name, chinese, math, english):
        """
        初始化方法
        :param name: 姓名
        :param chinese: 语文成绩
        :param math: 数学成绩
        :param english: 英语成绩
        """
        self.name = name
        self.chinese = chinese
        self.math = math
        self.english = english
        self.total = chinese + math + english  # 总分

    def __str__(self):
        return f"{self.name}\t{self.chinese}\t{self.math}\t{self.english}\t{self.total}"
# manager.py

import json
from .student import Student

class StudentManager:
    """学生信息管理系统类"""
    def __init__(self):
        # 存储学员数据 -- 列表
        self.student_list = []

    # 程序入口函数
    def run(self):
        # 加载文件里面的学员数据
        self.load_student()

        while True:
            # 显示功能菜单
            self.show_menu()
            # 用户输入目标功能序号
            action = input('请选择您想要进行的操作(0-退出):')

            # 根据用户输入的序号执行不同的功能
            if action == '1':
                # 新建学生信息
                self.add_student()
            elif action == '2':
                # 显示全部信息
                self.show_student()
            elif action == '3':
                # 查询学生信息
                self.search_student()
            elif action == '4':
                # 删除学生信息
                self.del_student()
            elif action == '5':
                # 修改学生信息
                self.modify_student()
            elif action == '0':
                # 退出系统
                self.save_student()
                print('欢迎再次使用【学生信息管理系统】!再见!')
                break
            else:
                print('输入错误,请重新选择!')

    # 显示功能菜单
    @staticmethod
    def show_menu():
        str_info = """**************************************************
欢迎使用【学生信息管理系统】V1.0
请选择你想要进行的操作
1. 新建学生信息
2. 显示全部信息
3. 查询学生信息
4. 删除学生信息
5. 修改学生信息

0. 退出系统
**************************************************"""
        print(str_info)

    # 添加学生信息
    def add_student(self):
        print('---------- 新建学生信息 ----------')
        name = input('请输入姓名:').strip()
        if not name:
            print('姓名不能为空!')
            return
        try:
            chinese = int(input('请输入语文成绩:'))
            math = int(input('请输入数学成绩:'))
            english = int(input('请输入英语成绩:'))
        except ValueError:
            print('成绩必须是整数!')
            return

        # 检查是否已有该学生
        if any(stu.name == name for stu in self.student_list):
            print(f'学生{name}已存在,无法重复添加!')
            return

        # 创建学生对象并添加到列表
        student = Student(name, chinese, math, english)
        self.student_list.append(student)
        print(f'成功添加学生:{student.name}')

    # 显示全部学生信息
    def show_student(self):
        print('---------- 显示全部学生信息 ----------')
        if not self.student_list:
            print('当前没有学生信息。')
            return
        print('姓名\t语文\t数学\t英语\t总分')
        print('-' * 30)
        for stu in self.student_list:
            print(stu)

    # 查询学生信息
    def search_student(self):
        print('---------- 查询学生信息 ----------')
        search_name = input('请输入要查询的学生姓名:').strip()
        if not search_name:
            print('姓名不能为空!')
            return
        for stu in self.student_list:
            if stu.name == search_name:
                print('姓名\t语文\t数学\t英语\t总分')
                print('-' * 30)
                print(stu)
                return
        print(f'未找到名为"{search_name}"的学生。')

    # 删除学生信息
    def del_student(self):
        print('---------- 删除学生信息 ----------')
        del_name = input('请输入要删除的学生姓名:').strip()
        if not del_name:
            print('姓名不能为空!')
            return
        for stu in self.student_list:
            if stu.name == del_name:
                confirm = input(f'确定要删除学生"{del_name}"吗?(y/n):').strip().lower()
                if confirm == 'y':
                    self.student_list.remove(stu)
                    print(f'成功删除学生:{del_name}')
                else:
                    print('删除操作已取消。')
                return
        print(f'未找到名为"{del_name}"的学生。')

    # 修改学生信息
    def modify_student(self):
        print('---------- 修改学生信息 ----------')
        modify_name = input('请输入要修改的学生姓名:').strip()
        if not modify_name:
            print('姓名不能为空!')
            return
        for stu in self.student_list:
            if stu.name == modify_name:
                print('请输入新的信息(留空表示不修改):')
                new_name = input(f'姓名(当前:{stu.name}):').strip()
                new_chinese = input(f'语文成绩(当前:{stu.chinese}):').strip()
                new_math = input(f'数学成绩(当前:{stu.math}):').strip()
                new_english = input(f'英语成绩(当前:{stu.english}):').strip()

                if new_name:
                    # 检查新姓名是否已存在
                    if any(s.name == new_name for s in self.student_list):
                        print(f'姓名"{new_name}"已存在,无法修改!')
                        return
                    stu.name = new_name
                if new_chinese:
                    try:
                        stu.chinese = int(new_chinese)
                    except ValueError:
                        print('语文成绩必须是整数,修改失败!')
                        return
                if new_math:
                    try:
                        stu.math = int(new_math)
                    except ValueError:
                        print('数学成绩必须是整数,修改失败!')
                        return
                if new_english:
                    try:
                        stu.english = int(new_english)
                    except ValueError:
                        print('英语成绩必须是整数,修改失败!')
                        return
                # 重新计算总分
                stu.total = stu.chinese + stu.math + stu.english
                print(f'学生"{stu.name}"的信息已更新。')
                return
        print(f'未找到名为"{modify_name}"的学生。')

    # 保存学生信息
    def save_student(self):
        print('---------- 保存学生信息 ----------')
        try:
            with open('students.json', 'w', encoding='utf-8') as f:
                # 将学生对象转换为字典列表
                final_stu_list = [{
                    "name": stu.name,
                    "chinese": stu.chinese,
                    "math": stu.math,
                    "english": stu.english,
                    "total": stu.total
                } for stu in self.student_list]
                # 写入JSON文件
                json.dump(final_stu_list, f, ensure_ascii=False, indent=4)
            print('学生信息已保存到"students.json"。')
        except Exception as e:
            print(f'保存失败:{e}')

解释

  • 模块封装:将Student类和StudentManager类分别放入student.pymanager.py模块中,组织结构更加清晰。
  • 相对导入:在manager.py中,使用from .student import Student进行相对导入,确保模块之间的依赖关系正确。
  • 数据持久化:通过JSON格式保存和加载学生信息,实现数据的持久化。

3. 包

包是将有联系的模块组织在一起的方式,通过包可以更好地管理和复用代码。

3.1 制作包

步骤

  1. 创建包文件夹:例如,创建一个名为mypackage的文件夹。
  2. 添加__init__.py文件:在mypackage文件夹内创建一个空的__init__.py文件,这个文件用于标识该文件夹为一个Python包。
  3. 添加模块:在包内添加相关的模块文件,例如my_module1.pymy_module2.py

示例

mypackage/
├── __init__.py
├── my_module1.py
└── my_module2.py

模块内容

# my_module1.py

print(1)

def info_print1():
    print('my_module1')
# my_module2.py

print(2)

def info_print2():
    print('my_module2')

解释

  • mypackage文件夹通过__init__.py文件被识别为一个包。
  • my_module1.pymy_module2.py是包内的两个模块,包含各自的功能。
  • 当导入包中的模块时,会自动执行模块内的顶级代码(如print(1)print(2))。

3.2 导入包

包中的模块可以通过多种方式导入,以便在其他Python脚本中使用。

导入包的方式

  1. import 包名.模块名
  2. from 包名.模块名 import 函数名
3.2.1 体验导入包

示例

# main.py

"""方法1"""
import mypackage.my_module1
mypackage.my_module1.info_print1()

"""方法2"""
from mypackage.my_module2 import info_print2
info_print2()

运行结果

1
my_module1
2
my_module2

解释

  • import mypackage.my_module1导入了包mypackage中的模块my_module1,并执行模块内的顶级代码print(1),然后调用info_print1()函数,输出my_module1
  • from mypackage.my_module2 import info_print2从包mypackage中的模块my_module2导入了info_print2函数,执行模块内的顶级代码print(2),然后调用info_print2()函数,输出my_module2

注意

  • 导入包中的模块时,模块内的顶级代码会被执行一次。
  • 使用不同的导入方式,可以根据需要选择最合适的调用方式。

总结

通过本节学习,您已经掌握了Python中模块和包的基本概念及其使用方法:

  • 模块

    • 模块是一个包含Python定义和语句的文件。
    • 通过import语句可以导入模块,并使用其中的功能。
    • 自定义模块需要遵循命名规则,并通过if __name__ == '__main__':进行测试,避免导入时自动执行测试代码。
    • Python在导入模块时遵循特定的搜索路径,确保模块能够被正确找到和导入。
    • 包是一个包含多个相关模块的文件夹,通过添加__init__.py文件标识。
    • 包有助于组织和管理大型项目中的模块,提升代码的可维护性和复用性。
    • 导入包中的模块时,可以使用多种导入方式,根据需求选择最合适的方式。
  • 实战应用

    • 将学生信息管理系统封装成包,通过模块化的设计,使系统结构更加清晰,便于扩展和维护。

掌握了模块和包的使用,您将在编程中更加游刃有余,能够高效地组织和管理代码,提升项目的开发效率和代码质量。下一篇博客中,我们将继续深入探讨异常处理,帮助您编写更加健壮和可靠的Python程序。

祝学习愉快,编程顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨胜增

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值