第6讲:函数=代码微波炉!一键加热复杂操作
温馨提示:学完本讲,你将用函数封装BMI计算器、开发年会抽奖程序,甚至用递归画出神奇分形树🌳
文章目录
一、为什么需要函数?告别重复搬砖!
生活比喻:微波炉 vs 函数
# 没有函数 → 每次热饭都要重写步骤
print("打开微波炉")
print("放入饭菜")
print("设置3分钟")
print("等待...")
print("取出热饭")
# 使用函数 → 封装成"热饭"微波炉
def heat_food(food, time=3):
print(f"加热{food}中...")
print(f"等待{time}分钟")
return f"热好的{food}"
# 一键热饭
breakfast = heat_food("包子") # 使用默认3分钟
lunch = heat_food("便当", 5) # 自定义5分钟
二、函数定义三要素
▶ 基础结构
def 函数名(参数1, 参数2=默认值):
"""文档字符串(说明函数功能)"""
# 函数体
return 返回值
▶ 动手实验①:智能BMI计算器
def calculate_bmi(height_cm, weight_kg):
"""
计算BMI指数并返回健康建议
:param height_cm: 身高(厘米)
:param weight_kg: 体重(公斤)
:return: (bmi值, 健康评语)
"""
height_m = height_cm / 100
bmi = weight_kg / (height_m ** 2)
if bmi < 18.5:
comment = "偏瘦,要多吃点哦"
elif 18.5 <= bmi < 24:
comment = "标准身材,继续保持!"
elif 24 <= bmi < 28:
comment = "微胖界代表,该运动啦"
else:
comment = "肥胖,健康预警!"
return round(bmi, 1), comment
# 使用示例
your_bmi, advice = calculate_bmi(175, 70)
print(f"BMI指数:{your_bmi} → {advice}")
三、参数传递的奥秘
位置参数 vs 关键字参数
# 位置参数 → 顺序必须正确
def create_user(name, age, city):
print(f"{name}|{age}岁|{city}")
create_user("小明", 25, "北京") # 正确
# 关键字参数 → 顺序无关
create_user(age=30, city="上海", name="小红") # 同样正确
默认参数:贴心预设值
def order_coffee(type="拿铁", size="大杯", sugar=50):
print(f"已下单:{size}{type},甜度{sugar}%")
order_coffee() # 默认拿铁大杯半糖
order_coffee("摩卡", "超大杯", 30) # 自定义
动手实验②:年会抽奖程序
import random
def lottery_draw(players, prizes):
"""
年会抽奖函数
:param players: 参与者列表
:param prizes: 奖品字典{奖品名: 数量}
:return: 中奖名单{奖品名: [中奖人]}
"""
winners = {prize: [] for prize in prizes}
# 随机打乱参与者
random.shuffle(players)
# 依次抽取奖品
for prize, count in prizes.items():
# 抽取指定数量中奖者
winners[prize] = players[:count]
# 移除已中奖者
players = players[count:]
return winners
# 使用示例
employees = ["张三", "李四", "王五", "赵六", "钱七"]
prize_pool = {"iPhone15": 1, "AirPods": 2, "红包500元": 3}
result = lottery_draw(employees, prize_pool)
print("🎉 中奖名单:")
for prize, names in result.items():
print(f"{prize} → {', '.join(names)}")
四、递归:函数调用自己的魔法
经典案例:斐波那契数列
def fibonacci(n):
"""返回第n个斐波那契数"""
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
# 打印前10项
for i in range(10):
print(fibonacci(i), end=" ") # 0 1 1 2 3 5 8 13 21 34
彩蛋实验:递归分形树
import turtle
def draw_tree(branch_len, t):
"""递归绘制分形树"""
if branch_len > 5: # 递归基线
# 绘制主干
t.forward(branch_len)
# 绘制右侧分支
t.right(20)
draw_tree(branch_len - 15, t)
# 绘制左侧分支
t.left(40)
draw_tree(branch_len - 15, t)
# 返回原位置
t.right(20)
t.backward(branch_len)
# 初始化画布
t = turtle.Turtle()
t.left(90)
t.up()
t.backward(100)
t.down()
t.color("green")
t.speed('fastest')
# 绘制分形树
draw_tree(75, t)
turtle.done() # 保持窗口打开
五、避坑指南:函数四大深坑
💥 陷阱1:修改可变默认参数
def add_item(item, cart=[]): # 默认值只创建一次!
cart.append(item)
return cart
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['苹果', '香蕉'] → 意外保留上次结果!
# 正确做法:用None作为默认值
def add_item(item, cart=None):
if cart is None:
cart = []
cart.append(item)
return cart
💥 陷阱2:忽略返回值
# 错误:没有保存计算结果
calculate_bmi(170, 65) # 返回值丢失!
# 正确:保存或使用返回值
bmi = calculate_bmi(170, 65)
💥 陷阱3:作用域混淆
discount = 0.9 # 全局变量
def apply_discount(price):
discount = 0.8 # 局部变量 → 不影响全局
return price * discount
print(apply_discount(100)) # 80
print(discount) # 0.9 → 全局未改变
💥 陷阱4:递归深度爆炸
# 错误:无基线条件的递归
def infinite_recursion():
infinite_recursion() # RecursionError
# 正确:确保有终止条件
六、动手实验③:表情包生成器
def create_meme(top_text, bottom_text, symbol="😂"):
"""
生成表情包函数
:param top_text: 顶部文字
:param bottom_text: 底部文字
:param symbol: 表情符号
:return: 表情包字符串
"""
width = max(len(top_text), len(bottom_text)) + 6
meme = [
"┌" + "─" * width + "┐",
f"│ {top_text.center(width-4)} │",
"│" + " " * width + "│",
f"│ {symbol * ((width-4)//len(symbol))} │",
"│" + " " * width + "│",
f"│ {bottom_text.center(width-4)} │",
"└" + "─" * width + "┘"
]
return "\n".join(meme)
# 使用示例
print(create_meme("代码又报错了", "但我不说是哪行", "😭"))
print(create_meme("Python学完", "升职加薪", "💰"))
七、总结与预告
✅ 今日函数魔法:
- 掌握函数定义与参数传递
- 封装BMI健康计算器
- 开发年会抽奖系统
- 实现递归分形树
- 绕过4大函数深坑
- 生成自定义表情包
➡️ 下讲剧透:
【列表】你的编程百宝箱!
你将学会:
- 用列表管理待办事项
- 实现《学生成绩分析系统》
- 开发《电影推荐引擎》原型
- 掌握列表推导式黑魔法✨
挑战任务:
- 修改表情包生成器,增加自定义边框符号功能(如用★替换─)
- 在评论区晒出你的分形树截图!
我是Alex,明早8:00解锁列表百宝箱!
函数冷知识:Python函数是第一类对象,可赋值给变量my_func = calculate_bmi