26e0a687创建于 2025年4月19日历史提交

第6周 Python 代码组织 (初级)

🔙 返回教学大纲

任务目标

上周 “对象类型” 主要是 Python 表达式 (expression) 方面的概念,而本周 “代码组织” 则主要是 Python 语句 (statement)、模块 (module) 和 软件包 (package) 等方面的概念。和写文章相似,最基础的固然是一个个词汇,但划分段落、谋篇布局也是很重要的。编写程序和写文章虽然有很多相似的地方 (比如都可以虚构,都需要组织),但有个重要的区别是:因为编程追求自动化,所以编程有个基本原则是 “代码不要重复” (Don't Repeat Yourself, DRY)。这就要求我们在代码编写中通过 抽象 (abstraction) 和 复用 (reuse) 来减少重复的逻辑或数据,提高代码的可维护性。同理,我们安装和利用第三方软件包 (PyPI),也是为了 “不要重新发明轮子” (Don't Reinvent the Wheel)。

  1. Fork 第06周打卡 仓库至你的名下,然后将你名下的这个仓库 Clone 到你的本地计算机

  2. 用 VS Code 打开项目目录,新建一个 environment.yml 文件,指定安装 Python 3.12,然后运行 conda env create 命令创建 Conda 环境

  3. 创建一个 guessing_game.py 文件,复制粘贴以下代码,运用 pdb 调试器理解其运行流程:

    import random
    
    
    def guessing_game():
        # 生成 1 到 100 之间的随机整数
        secret_number = random.randint(1, 100)
        n = 0
    
        print("欢迎来到猜数字游戏!我已经想好了一个 1 到 100 之间的数字,你可以开始猜啦。")
    
        while True:
            n += 1
            # 获取玩家输入
            guess = input(f"(第 {n} 次尝试) 请输入你猜的数字 (输入整数, 或者输入 q 回车退出): ")
            guess = guess.strip()  # 去除多余空白字符
    
            if guess == "q":
                break
            
            try:
                guess = int(guess)
            except ValueError:
                print("输入无效🙅,请输入一个整数。")
                continue
            
            if guess < 1 or guess > 100:
                print("输入无效🙅,输入值应该在 1~100 之间。")
                continue
            
            if guess == secret_number:
                print("恭喜你🎉,猜对了!")
                break
    
            if guess < secret_number:
                print("猜的数字太小了,再试试⤴️。")
                continue
    
            if guess > secret_number:
                print("猜的数字太大了,再试试⤵️。")
                continue
            
            raise NotImplementedError
    
        print("游戏结束,再见👋。")
    
    
    if __name__ == "__main__":
        guessing_game()
    
  4. 创建一个 flow_controls.py 文件,让豆包 (或 DeepSeek 等任何大模型) 生成例子,尝试运行,体会理解以下 Python 流程控制语句:

    • for 迭代循环 (iteration loop)
    • while 条件循环 (conditional loop)
    • break 打断跳出循环
    • continue 跳至下一轮循环
    • for...else 循环未被打断的处理
    • if 条件分支
    • if...elif[...elif] 多重条件分支
    • if...else 未满足条件的处理
    • try...except[...except...else...finally] 捕捉异常的处理
    • raise 主动抛出异常
  5. 创建一个 mylib.py 模块 (module),在里面定义以下函数,再创建一个 myjob.py 脚本 (script),从 mylib.py 导入函数并尝试调用:

    • 定义函数 func1,没有形参,没有返回值
    • 定义函数 func2,没有形参,有返回值
    • 定义函数 func3,只有一个 位置形参 (positional parameter),先尝试传入 位置实参 (positional argument) 调用,再尝试传入 命名实参 (named argument) 调用,再尝试不传实参 (会报错)
    • 定义函数 func4,只有一个 命名形参 (named parameter),先传入 位置实参 调用,再传入 命名实参 调用,再尝试不传实参 (取默认值)
    • 定义函数 func5,接受多个位置形参和命名形参,尝试以位置/命名各种不同方式传入实参,注意位置参数必须排在命名参数之前
    • 定义函数 func6,在形参列表中使用 / 来限定只接受位置实参的形参
    • 定义函数 func7,在形参列表中使用 * 来限定只接受命名实参的形参
    • 定义函数 func8,在位置形参的最后,在形参名称前使用 * 允许传入任意数量的位置实参 (被打包为元组)
    • 定义函数 func9,在命名形参的最后,在形参名称前使用 ** 允许传入任意数量的命名实参 (被打包为字典)
    • 定义函数 func10,接受两个位置形参,一个命名形参,尝试在调用时使用 * 将可迭代对象 (如元组或列表) 自动解包,按位置实参传入
    • 定义函数 func11,接受一个位置形参,两个命名形参,尝试在调用时使用 ** 将映射对象 (如字典) 自动解包,按命名实参传入
    • 定义函数 func12,给函数添加 内嵌文档 (docstring),给形参和返回值添加 类型注解 (type annotation),提高函数签名的可读性
  6. mylib 模块转变为 软件包 (package) 安装进当前的 Conda 环境来使用

    • myjob.py 脚本移动至 scripts/myjob.py,再次尝试运行,会发现 import mylib 失败,这是由于 mylib 并没有打包成 软件包 (package) 安装
    • mylib.py 模块移动至 src/mypkg/mylib.py,创建 src/mypkg/__init__.py 文件,准备好软件包的源代码
    • 创建 pyproject.toml 配置文件,按照 文档 填写基本的软件包信息
    • pyproject.toml 配置文件里,按照 文档 填写软件包的 构建 (build) 配置
    • 使用 pip install -e . 以本地可编辑模式把当前软件包安装进当前 Conda 环境
    • 修改 environment.yml 文件,使得 conda env create 自动安装本地可编辑软件包

操作演示

浏览器观看 手机扫码观看
Part 1.1. 猜数字游戏调试运行-1
本次课程主要讲解代码组织问题,包括表达式、语句、模块和软件包等方面的知识。首先,通过克隆课程仓库并编辑环境文件,创建一个名为06的虚拟环境。然后,在终端中运行Python命令,使用PDB调试器运行猜数字游戏代码。最后,重点理解编程中的基本语句,如定义函数、循环和条件判断等。会议内容还涉及网络访问问题,以及如何清理和重建虚拟环境。(智能总结由机器自动生成,仅供参考)
二维码
Part 1.2. 猜数字游戏调试运行-2
讨论了猜数字游戏程序的运行过程、Python中的流程控制语句、循环和判断逻辑以及未实现错误处理。首先,程序会生成一个1到100之间的随机数作为秘密数字,进入无限循环,提示用户猜测数字,并尝试通过输入的数字与随机数进行比较。在调试过程中,可以通过按N键查看当前行的代码,或者使用PDB工具进行更详细的调试。其次,Python中的流程控制语句try、except和continue用于处理可能出现的异常和跳过当前循环的剩余部分。再次,程序中的while循环和判断逻辑会根据输入的数字是否在1到100之间来控制运行。最后,在编写代码时应考虑各种情况,并在前面加入判断语句,以处理其他乱七八糟的情况。(智能总结由机器自动生成,仅供参考)
二维码
Part 2. 流程控制语句举例验证
主要讲解了Python中的流程控制语句,包括循环和分支的概念。首先,通过猜数字游戏介绍了循环和分支的基本概念,并强调了理解代码的重要性。接着,详细解释了for和while两种循环的使用方法,以及如何使用点操作符解包键值对,并通过表达式计算出一个对象。然后,通过实例演示了这两种循环的使用方法,并强调了任何可迭代对象都可以用于for和while循环。最后,讲述了如何使用大模型进行编程学习,包括生成各种程序例子来帮助理解Python中的分支语句、if else、else if、try except、finally等的使用,并强调了在程序中适当抛出异常以改变运行流程的重要性。同时,建议同学们自己生成例子进行练习,利用大模型生成的综合复杂例子有助于学习。(智能总结由机器自动生成,仅供参考)
二维码
Part 3. 模块里定义函数,脚本里调用函数
讨论了Python中函数的定义、调用、参数传递和类型注解等基本概念。首先,强调了函数是编写程序的基本单元,可以通过在my lib模块中定义并调用函数来观察其运行结果。其次,介绍了如何通过给函数加上返回值和错误处理,以及使用try-except语句捕获并打印错误信息,来实现正确的参数传递和错误处理。此外,还讲解了如何正确定义和调用函数,包括位置形参和命名形参的传递方式,以及在实际操作中需要注意的规则。最后,通过实例演示了如何使用Python中的字典和元组进行参数传递,并强调了在编写代码时打好基础的重要性。(智能总结由机器自动生成,仅供参考)
二维码
Part 4. 软件包的配置、构建和安装
讨论了函数在模块中定义和软件包的转化问题,以及如何创建和管理Python软件包。首先,讲者强调了将脚本移动到其他文件夹后,运行时会出现找不到模块的问题,因此建议规范的做法是将模块转化成软件包,并安装后才能使用。其次,详细讲解了如何创建一个软件包,包括将模块放到软件包下、设置跳过重构、创建名为init_PY的文件和py project的配置文件等步骤。同时,也介绍了Python软件包的制作过程,包括在配置中设置项目信息、版本号等信息,并强调了遵循一定的规则和注意事项。此外,还讨论了如何使用hatch工具进行软件包的构建和安装,以及在Python环境中构建和安装软件包的方法。最后,讲解了如何在Python中导入和运行模块,并在环境创建和软件包管理方面进行了详细讲解。(智能总结由机器自动生成,仅供参考)
二维码

参考资料


🔙 返回教学大纲