Python 函数与模块化设计

https://html.cafe/x57235644

👨‍🏫 课程引言:从“重复劳动”中解脱

在之前的课程中,我们学习了变量和循环。今天,我们要攻克编程中最核心的概念之一:函数 (Function)

很多初学者认为函数只是“把代码包起来”。但从计算机科学的角度看,函数的本质是抽象 (Abstraction)封装 (Encapsulation)。它就像工厂里的模具,定义一次,就能生产出千千万万个标准或定制的产品。

今天,我们将通过一个“星空生成器”的项目,分四个阶段,循序渐进地理解函数的定义、调用、参数传递以及多态性。

阶段 1:面向过程的困境

假设我们现在的任务很简单:在屏幕中心画一颗黄色的五角星。

如果我们不使用函数,通过基础绘图指令(这里使用伪代码模拟 Python Turtle 或绘图库的逻辑),代码是线性的,从上到下执行。

# 1. 设置颜色
fill_color('yellow')
begin_fill()

# 2. 绘制五角星的五条边 (硬编码逻辑)
for i in range(5):
    forward(50)      # 向前移动 50 像素
    right(144)       # 向右旋转 144 度

end_fill()

图示:最原始的代码执行结果

🤔 思考: 如果你需要在屏幕的四个角落各画一颗星星,你需要把上面这几行代码复制粘贴 4 次吗?如果要画 100 颗呢?如果你突然想把所有的星星从黄色改成红色,你需要修改多少处代码?
这就是“重复代码”带来的维护灾难。

阶段 2:函数的定义与封装

为了解决重复劳动,我们将绘制星星的逻辑打包。在 Python 中,我们使用 def 关键字来定义函数。

现在,我们创造了一个名为 draw_star 的“模具”。定义它的时候,星星并不会出现;只有当我们调用它时,星星才会产生。

任务: 封装代码,并循环调用 100 次,在随机位置生成星星。

import random

# --- 定义函数 (制作模具) ---
def draw_star():
    # 所有的绘图细节都被藏在这里面了
    fill_color('yellow')
    begin_fill()
    for i in range(5):
        forward(30)      # 注意:这里的缩进是函数的一部分
        right(144)
    end_fill()

# --- 主程序 (使用模具) ---
for i in range(100):
    x = random.randint(0, 800)
    y = random.randint(0, 600)
    goto(x, y)      # 移动到随机位置
    draw_star()     # 调用函数!
💡 核心概念:封装 (Encapsulation) 此时的函数虽然方便,但它是“死”的。所有的星星都一模一样(大小固定、角度固定)。这是一个没有参数的函数。

阶段 3:参数——赋予函数灵活性

现实中的星星不会整齐划一地头朝上。为了让画面更自然,我们需要控制星星的旋转角度

我们在函数定义的括号里加入一个变量名 angle。这个变量叫做形参 (Parameter)。它就像是模具上的一个“旋钮”,允许我们在调用时传入不同的数值。

任务: 修改函数,让每颗星星都有随机的旋转角度。

# 定义带有一个参数的函数
def draw_star(angle):
    set_heading(angle)  # 使用传入的角度参数!
    
    fill_color('yellow')
    begin_fill()
    for i in range(5):
        forward(30)
        right(144)
    end_fill()

# 主程序
for i in range(100):
    x = random.randint(0, 800)
    y = random.randint(0, 600)
    r = random.randint(0, 360) # 生成随机角度
    
    goto(x, y)
    draw_star(r)  # 将随机角度 r 传给 angle

阶段 4:多参数与完全定制

最后,为了模拟真实的夜空,星星不仅方向不同,大小颜色也应该不同。这需要我们进一步扩展函数的接口。

我们在函数定义中增加 size 参数。现在,这个函数变得非常强大,它可以绘制任意角度、任意大小的星星。

任务: 生成 100 颗大小不一、旋转各异的星星,构成最终的星空图。

# 定义带有两个参数的函数:角度和大小
def draw_star(angle, size):
    set_heading(angle)
    
    # 边长不再是固定的 30,而是由 size 参数决定
    edge_len = size
    
    fill_color('yellow')
    begin_fill()
    for i in range(5):
        forward(edge_len) # 使用参数!
        right(144)
    end_fill()

# 主程序:创造丰富多彩的世界
for i in range(100):
    x = random.randint(0, 800)
    y = random.randint(0, 600)
    
    r = random.randint(0, 360)
    s = random.randint(10, 50) # 随机大小 10 到 50
    
    goto(x, y)
    draw_star(r, s) # 传入两个实参
🎓 教授总结 通过这四个步骤,我们从“写死代码”进化到了“通用模具”。
函数让我们的代码:
1. 可读性更强:`draw_star()` 比 5 行几何指令更易读。
2. 复用性更高:写一次,用无数次。
3. 易于维护:如果要修改星星的形状,只需修改函数定义一处即可。