函数
这是什么:函数 = 把一段代码打包、起个名字的复用单位,用 def 定义,调用时才真正跑起来。
为什么用:代码越写越长,同一段逻辑到处复制粘贴?改一处就得改五处。函数让代码只写一次、到处调用,以后修改也只动一个地方。
如何用:本章从 def greet(name) 出发,讲清参数、返回值,最后写一个带默认值的实用函数。
def:定义函数
def greet(name):
print(f"你好,{name}!")
greet("小青蛙")
greet("世界")
你会看到:
你好,小青蛙!
你好,世界!
def 就是 define(定义)的缩写。括号里的 name 叫参数——函数的入口,调用时传什么,函数里的 {name} 就换成谁。
关键一点:定义不执行,调用才执行。写好 def 只是造好了工具,greet("小青蛙") 才是按下启动按钮。
参数默认值与 return
def add(a, b=10):
return a + b
print(add(5)) # b 没传,用默认值 10
print(add(5, 2)) # b 传了 2,默认值作废
你会看到:
15
7
b=10 是默认参数:调用时可以不传。而 return 是函数的出口——把结果交还给调用处,所以 add(5) 整体就代表 15,能直接塞进 print()。没有 return 的函数返回 None(表示"啥也没有")。
为什么要函数
- 一次定义,处处调用:逻辑要改,只改一处
- 名字即说明:
check_score()看名字就知道干什么 - 分而治之:大程序拆成小函数,一次只盯一块
逐概念解读
| 写法 | 作用 |
|---|---|
def greet(name): |
定义函数 greet,接收一个参数 |
greet("小青蛙") |
调用:函数体这时才真正执行 |
def add(a, b=10): |
参数 b 带默认值,调用时可不传 |
return a + b |
结束函数,把结果交回调用处 |
print(add(5)) |
add(5) 的返回值 15 被塞进 print |
记忆口诀
def 造工具,参数是入口,return 是出口;定义不跑,调用才跑。
❓ 常见问题
Q1:函数里明明 print 了,为什么拿不到结果?
print 只负责显示给人看,不负责把值交还给程序。看这个翻车现场:
def add(a, b):
print(a + b) # 只显示,没交还
result = add(1, 2)
print(result)
你会看到 3 后面跟着一个 None。
原因:函数没写 return,Python 就默认让它交还 None——所以 result 接住的是个空。
修复:把函数里的 print(a + b) 改成 return a + b,result 就真的是 3 了。
举一反三:记住分工——想"要结果"用 return,想"给人看"才 print;两者不冲突,函数里可以 print 完再 return。另外 return 一执行,函数立刻收工,写在它后面的代码不会跑。
Q2:定义了函数,运行却一点反应都没有?
定义不执行,调用才执行——只写 def 只是造好了工具,还没按下启动按钮。
修复:在 def 的下面补一行调用,比如 greet("小青蛙"),再运行。
举一反三:把调用写在 def 前面也不行,会报 NameError: name 'greet' is not defined——Python 从上往下执行,工具还没造好就被叫了。所以规矩是:先定义,后调用。
Q3:参数多了,记不住顺序怎么办?
指名道姓传参(关键字参数),顺序就无所谓了:
def intro(name, age):
print(f"{name} 今年 {age} 岁")
intro(age=3, name="小青蛙") # 名字对上就行,顺序随便
你会看到:
小青蛙 今年 3 岁
参数一多(三四个以上),intro(age=3, name="小青蛙") 比光溜溜的 intro("小青蛙", 3) 好读得多——别人看一眼就知道每个值是给谁的,这也是写团队代码的好习惯。
Q4:函数能一次交还两个结果吗?
能,return 后面跟两个值打包交还,左边用同样多的变量接住:
def split_seconds(total):
return total // 60, total % 60 # // 是整除(取商),% 是取余
minutes, seconds = split_seconds(125)
print(minutes, seconds)
你会看到:
2 5
125 秒拆成了 2 分 5 秒。执行细节:右边两个值先打包成一组再交回来,左边按顺序拆开装进 minutes 和 seconds——和变量那章的 a, b = b, a 是同一套"打包-拆包"功夫。
Q5:函数里还能调用别的函数吗?
能,而且大程序就是靠这个搭起来的:
def greet(name):
return f"你好,{name}"
def shout(name):
print(greet(name) + "!!")
shout("小青蛙")
你会看到:
你好,小青蛙!!
shout 执行到 greet(name) 时,会暂停自己的活、先让 greet 干完拿到"你好,小青蛙",再拼接上"!!"打印。小函数搭大程序:每个函数只管一小块,互相调用拼出复杂功能,跟积木一个道理。
🎯 什么时候用它
- 同一段逻辑要用多次:校验手机号格式、算运费、生成统一格式的日期——写成一个函数,十处调用一处维护,改需求不用满篇找。
- 把大问题切小:写"学生成绩管理系统",拆成录入、算平均、打印报表三个函数,一次只盯一块,写完一块测一块。
- 团队协作的接口:你写
calculate(),同事直接调用,不用懂内部细节——函数名就是团队之间的"说明书",程序越大越离不开。
📝 本章小结
- 定义只是造工具,调用才真正执行;调用要写在定义之后
- 没写 return 的函数返回
None;return交还结果,print只管显示 - 参数是入口:可带默认值,也能指名道姓(关键字参数)乱序传
return可以一次交还多个值,左边用同样多的变量接住- 大程序拆成小函数,一次只盯一块;函数体里还能调用别的函数
记忆锚点:函数像豆浆机——豆子(参数)从入口倒进去,一键启动(调用)才干活,豆浆(返回值)从出口倒出来;机器本身(def)安安静静待在厨房,不按按钮它不转。
动手改
- 写一个
def bye(name):打印"再见,xxx!",调用两次试试 - 把 greet 改成
def greet(name="朋友"):,然后greet()一个参数都不传,看看打印什么 - 写
def is_even(n):,用return n % 2 == 0判断偶数,打印is_even(4)和is_even(7)的结果
下一章:综合练习,把四章所学拧成一个能玩的小游戏 🐸