注:学习资料来源<尚硅谷>
视频:点击跳转
代码仓库:pythonStudy
函数是 Python 编程中最核心的概念之一。作为一名开发者,你一定听过“不要重复造轮子”这句话——函数就是让我们把一组逻辑封装起来,在需要时重复使用,既能减少代码量,又能提升可读性。今天这篇博客将带你从零开始,系统掌握 Python 函数的所有关键知识点。
1. 函数的概念与分类
1.1 什么是函数?
函数 是组织好的、可重复使用的、用来实现单一或相关联功能的代码块。
打个比方:函数就像你家里的智能场景面板,你提前把“回家模式”设置好——打开灯光、拉上窗帘、播放音乐。之后你只需要说一句“回家模式”,所有设置好的动作就会自动执行。函数的道理一模一样,提前写好一段代码,需要时直接调用即可。
使用函数能带来几个明显的好处:
减少重复:相同逻辑只写一次,到处调用。
结构清晰:把复杂程序拆分成若干个小模块。
便于维护:修改一处,所有调用的地方都会生效。
易于复用:一个函数写好,可以在不同项目里多次使用。
1.2 Python 函数的三大类
Python 中的函数可以分为三类:
内置函数
Python 自带的函数,比如print()、len()、sum()、type()等,不需要额外导入就能直接用。
📚 官方内置函数文档模块提供的函数
需要先导入对应的模块才能使用。例如math.sqrt()、random.randint()、os.path.join()。
📚 官方模块索引自定义函数
由开发者自己使用def关键字定义的函数。这也是我们今天的重头戏。
2. 函数的基本使用
2.1 定义函数
最简单的函数定义长这样:
def 函数名():
函数体def是定义函数的关键字。函数名要符合标识符命名规范(字母、数字、下划线,不能以数字开头)。
定义完函数不会立即执行,必须调用才会运行。
下面是一个欢迎函数:
def welcome():
print("欢迎来到 Python 课堂!")
print("Python 让编程更简单!")2.2 调用函数
调用函数只需在函数名后加上小括号:
welcome() # 函数体内的代码会立即执行
welcome() # 可以多次调用⚠️ 注意:函数必须先定义,后调用。如果顺序反了,Python 会报错。
3. 函数的参数
没有参数的函数只能做固定的事;有了参数,函数就变得灵活而强大。
3.1 参数的作用
假设我们想写一个点餐程序,没有参数时:
def order():
num = 1
dish = "辣椒炒肉"
print(f"您点的是:{num}份 {dish}")
order()这个函数每次点餐都只能是一份辣椒炒肉,明显不够用。加了参数之后:
def order(num, dish):
print(f"您点的是:{num}份 {dish}")
order(1, "辣椒炒肉")
order(2, "辣子鸡")3.2 形参 vs 实参
形参(形式参数):定义函数时括号里的变量,用来接收调用时传进来的值。
实参(实际参数):调用函数时实际传入的具体数据。
形参只在函数体内有效,函数执行完毕,形参也随之销毁。
3.3 位置参数
调用时,按照形参定义的顺序依次传入实参,这就是位置参数。
def order(num, dish):
print(f"您点的是:{num}份 {dish}")
order(3, "宫保鸡丁") # 3 -> num, "宫保鸡丁" -> dish⚠️ 实参的个数、顺序必须和形参一致,否则会出错或造成数据错乱。
3.4 关键字参数
不想记顺序?可以用 形参名=值 的方式传递,这就是关键字参数。
def greet(name, gender, age, height):
print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")
greet(name="张三", gender="男", age=18, height=172)
greet(height=172, age=18, gender="男", name="张三") # 顺序完全自由位置参数和关键字参数可以混用,但位置参数必须放在关键字参数之前。
greet("张三", "男", height=172, age=18) # ✅ 正确
# greet(height=172, age=18, "张三", "男") # ❌ 错误3.5 限制传参方式(/ 和 *)
如果你想强制调用者使用特定的传参方式,可以用 / 和 *:
/前面的参数只能使用位置参数。*后面的参数只能使用关键字参数。
def greet(name, /, gender, *, age, height):
print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")
greet("张三", "男", age=18, height=172) # ✅
greet("张三", gender="男", age=18, height=172) # ✅
# greet(name="张三", gender="男", age=18, height=172) # ❌ name在/前面,不能用关键字3.6 参数默认值
有些参数大部分情况下都取同一个值,这时可以给它一个默认值。调用时如果不传,就使用默认值;传了则覆盖。
def greet(name, gender, age, height, msg="你好"):
print(f"我叫{name},性别{gender},年龄{age},身高{height}cm")
print(f"我想说:{msg}")
greet("张三", "男", 18, 172) # msg = "你好"
greet("张三", "男", 18, 172, "hello") # msg = "hello"⚠️ 有默认值的形参必须放在所有必选参数(无默认值)的后面,否则语法错误。
3.7 可变参数:*args 和 **kwargs
如果不知道调用者会传多少个参数,怎么办?用可变参数!
*args:把多个位置参数打包成一个元组。**kwargs:把多个关键字参数打包成一个字典。
def test1(*args):
print("位置参数元组:", args)
test1("张三", "男", 18, 172)
# 输出:位置参数元组: ('张三', '男', 18, 172)
def test2(**kwargs):
print("关键字参数字典:", kwargs)
test2(name="张三", gender="男", age=18, height=172)
# 输出:关键字参数字典: {'name': '张三', 'gender': '男', 'age': 18, 'height': 172}两者同时使用时,*args 必须放在 **kwargs 之前。
def func(a, b, *args, c="Python", **kwargs):
print("a:", a, "b:", b, "c:", c)
print("args:", args)
print("kwargs:", kwargs)
func("张三", "男", "抽烟", "喝酒", age=18, height=172)3.8 特殊的字面量 None
None 表示空值、无意义。它的类型是 NoneType。
在布尔判断中,
None被视为False。不能与数字相加,也不能与字符串拼接。
函数如果没有写
return,或只写了return但不带值,默认返回的就是None。
常见用法:
msg = None # 暂时不清楚 msg 将来存什么
if not msg:
print("msg 是空的")4. 返回值
函数不仅能干活,还能把结果“交回来”,这就是返回值。
使用 return 关键字:
立即结束函数运行。
把
return后面的值作为函数的返回值抛给调用者。
def add(n1, n2):
return n1 + n2
result = add(100, 200)
print(result) # 300没有 return 的函数,或者只写 return 的函数,返回值默认为 None。
result = print("hello") # print 没有返回值
print(result) # None5. 全局作用域与局部作用域
作用域决定了变量的可访问范围。
5.1 全局变量
在函数外部定义的变量称为全局变量,整个程序都可以访问它。
5.2 局部变量
函数内部定义的变量称为局部变量,只能在函数体内使用。函数调用结束,局部变量就被销毁了。
5.3 global 关键字
如果想在函数内部修改全局变量的值,而不是创建一个同名局部变量,需要用 global 声明。
a = 100
def test():
global a # 声明 a 是全局变量
a = 300
print("函数内 a:", a)
test()
print("全局 a:", a) # 300如果没有
global,函数内部的a = 300只会创建一个新的局部变量,不会影响外部的a。
生命周期对比:
局部变量:函数调用时创建,函数结束时销毁。
全局变量:程序启动时创建,程序结束时销毁。
# 局部变量的生命周期
def local_demo():
m = 100
m += 1
print(f"局部 m: {m}")
local_demo()
local_demo() # 每次 m 都重新初始化为 100
# 全局变量生命周期
n = 100
def global_demo():
global n
n += 1
print(f"全局 n: {n}")
global_demo()
global_demo()
global_demo() # n 会持续累加6. 函数的嵌套调用
一个函数在执行过程中可以调用另一个函数,这被称为嵌套调用。
def speak(msg):
print("---" * 10)
print(msg)
print("---" * 10)
def greet(name, msg):
print(f"我叫{name},我想说的话在下面:")
speak(msg)
print("我想说的结束了")
greet("张三", "你好啊")多层嵌套也很常见,逻辑像俄罗斯套娃一样一层层深入,再一层层返回。
def test1():
print("进入 test1")
test2()
print("退出 test1")
def test2():
print("进入 test2")
test3()
print("退出 test2")
def test3():
print("进入 test3")
print("*** 执行 test3 ***")
print("退出 test3")
test1()7. 递归调用
递归是函数自己调用自己的一种编程技巧,非常适合解决可以拆分成子问题的问题。
但是递归必须要有终止条件,否则就会无限循环下去,直至栈溢出。
# 从大到小打印
def welcome(n):
print(f"你好啊 {n}")
if n > 1:
welcome(n - 1)
welcome(5)上面的代码会依次输出 “你好啊 5” 到 “你好啊 1”。
如果换成从小到大打印呢?只需要把 print 放到递归调用之后:
def welcome_asc(n):
if n > 1:
welcome_asc(n - 1)
print(f"你好啊 {n}")
welcome_asc(5)经典递归:求阶乘
def factorial(num):
if num == 0:
return 1
else:
return num * factorial(num - 1)
print(factorial(5)) # 120
print(factorial(6)) # 7208. 函数说明文档
给函数加文档是一种好习惯。你只需要在函数体开头用三引号字符串写下说明即可。
def add(n1, n2):
"""
计算两个数相加的结果。
:param n1: 第一个数
:param n2: 第二个数
:return: 二者相加的结果
"""
return n1 + n2在 IDE 或 Jupyter 中,鼠标悬停或使用 help(add) 就能看到你写的文档,极大的方便了自己和团队其他成员。
9. 综合案例:健身挑战赛
最后,我们把前面学到的知识串起来,写一个有趣的小应用——记录三天健身数据,判断是否挑战成功。
def calc_total(*nums):
"""计算总运动量"""
return sum(nums)
def calc_avg(total, days=7):
"""计算平均值"""
return total / days
def check_success(total, goal=120):
"""判断挑战是否成功"""
if total >= goal:
return "✅ 恭喜!挑战成功!"
else:
return "❌ 抱歉!挑战失败!"
def main(title, duration, goal):
print(f"【{title}】【{duration}天】挑战赛(请输入每天的数量)")
num1 = int(input("第1天:"))
num2 = int(input("第2天:"))
num3 = int(input("第3天:"))
total = calc_total(num1, num2, num3)
avg = calc_avg(total, duration)
result = check_success(total, goal)
print(f"\n【{title}】【{duration}天】健身总结")
print(f"总数:{total},平均值:{avg:.1f}")
print(result)
# 启动挑战
main("俯卧撑", 3, 40)运行这个程序,你就可以模拟一个三天俯卧撑挑战,程序会自动计算总数、平均值,并告诉你是否达成了目标。这里面用到了自定义函数、参数、可变参数、默认参数、返回值、用户输入、格式化输出等一系列知识,是函数综合运用的绝佳练习。
小结
恭喜你!现在你已经掌握了 Python 函数的全貌:
如何定义与调用函数
参数的各种玩法(位置、关键字、默认值、可变参数)
返回值与
None变量的作用域与
global嵌套调用与递归
编写文档和综合实战
下一步,可以尝试把今天学到的东西用在你的实际项目中,把重复的代码重构成函数。当你的函数越写越顺手时,你就真正走上了 Python 进阶之路。
练习建议:按照本文的知识点顺序,分别创建对应的 Python 文件,逐一练习,代码量不用多,重在体会每种用法的使用场景。
Happy Coding!