🐸 青蛙编程网
首页 / Python / Python 基础 / 7. 函数

函数

这是什么:函数 = 把一段代码打包、起个名字的复用单位,用 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(表示"啥也没有")。

为什么要函数

  1. 一次定义,处处调用:逻辑要改,只改一处
  2. 名字即说明:check_score() 看名字就知道干什么
  3. 分而治之:大程序拆成小函数,一次只盯一块

逐概念解读

写法 作用
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)安安静静待在厨房,不按按钮它不转。

动手改

  1. 写一个 def bye(name): 打印"再见,xxx!",调用两次试试
  2. 把 greet 改成 def greet(name="朋友"):,然后 greet() 一个参数都不传,看看打印什么
  3. 写 def is_even(n):,用 return n % 2 == 0 判断偶数,打印 is_even(4) 和 is_even(7) 的结果

下一章:综合练习,把四章所学拧成一个能玩的小游戏 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。