📦 14. 函数详解
本章概述
学习 Python 函数的定义、参数、返回值、作用域等。 预计学习时间:70 分钟
14.1 函数定义
函数就是一段可以重复使用的代码块。
基本格式
def 函数名(参数列表):
"""函数文档字符串"""
函数体
return 返回值示例
def greet(name):
"""打招呼的函数"""
print(f"你好,{name}!")
# 调用函数
greet("Tom") # 你好,Tom!
greet("Jerry") # 你好,Jerry!函数命名规范
- 小写字母 + 下划线(蛇形命名)
- 动词开头,见名知意
- 例如:
get_name(),calculate_sum(),print_info()
14.2 函数参数
位置参数
按顺序传递参数:
def add(a, b):
return a + b
add(3, 5) # 8(a=3, b=5)关键字参数
按参数名传递,可以不按顺序:
def greet(name, age):
print(f"我叫{name},今年{age}岁")
greet(age=18, name="Tom") # 可以不按顺序位置参数和关键字参数可以混合用
但位置参数必须在关键字参数前面:
greet("Tom", age=18) # ✅ 可以 # greet(name="Tom", 18) # ❌ 不行
默认参数
参数有默认值,调用时可以不传:
def greet(name, greeting="你好"):
print(f"{greeting},{name}!")
greet("Tom") # 你好,Tom!
greet("Tom", "Hello") # Hello,Tom!
greet("Tom", greeting="Hi") # Hi,Tom!默认参数的坑
默认参数不要用可变对象!
# ❌ 错误:默认参数用了可变对象 def add_item(item, lst=[]): lst.append(item) return lst print(add_item(1)) # [1] print(add_item(2)) # [1, 2](不是[2]!因为默认列表被复用了) # ✅ 正确:用None当默认值 def add_item(item, lst=None): if lst is None: lst = [] lst.append(item) return lst
可变参数 *args
接收任意多个位置参数,变成一个元组:
def sum_all(*args):
print(args) # args是一个元组
total = 0
for n in args:
total += n
return total
sum_all(1, 2, 3) # 6
sum_all(1, 2, 3, 4, 5) # 15关键字可变参数 **kwargs
接收任意多个关键字参数,变成一个字典:
def print_info(**kwargs):
print(kwargs) # kwargs是一个字典
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Tom", age=18, gender="男")参数组合
参数定义的顺序必须是:
- 位置参数
- 默认参数
- *args
- 命名关键字参数
- **kwargs
def func(a, b, c=0, *args, d=1, **kwargs):
print(a, b, c, args, d, kwargs)什么时候用 *args / **kwargs?
- 参数数量不确定时
- 写装饰器时
- 传递参数给另一个函数时
14.3 返回值 return
基本用法
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8返回多个值
Python 特色
Python 函数可以返回多个值,本质是返回一个元组。
def calc(a, b):
return a + b, a - b, a * b
sum_val, diff, product = calc(10, 3)
print(sum_val, diff, product) # 13 7 30没有 return
函数没有 return 时,默认返回 None:
def say_hello():
print("hello")
result = say_hello()
print(result) # None多个 return
函数可以有多个 return,遇到第一个 return 就返回:
def get_grade(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 60:
return "C"
else:
return "D"14.4 函数文档字符串 docstring
函数开头的字符串,用来说明函数的用途、参数、返回值等。
def add(a, b):
"""
计算两个数的和
参数:
a (int/float): 第一个数
b (int/float): 第二个数
返回:
int/float: 两个数的和
示例:
>>> add(3, 5)
8
"""
return a + b查看文档字符串
help(add) # 查看帮助信息
print(add.__doc__) # 直接看文档字符串好习惯
重要的函数一定要写文档字符串,方便自己和别人理解。
14.5 变量作用域
局部变量 vs 全局变量
x = 10 # 全局变量
def func():
y = 20 # 局部变量,只能在函数内用
print(x) # 可以读全局变量
print(y)
func()
# print(y) # ❌ 报错,y是局部变量,外面访问不到global 关键字
在函数内修改全局变量,需要用 global 声明:
x = 10
def func():
global x # 声明x是全局变量
x = 20 # 修改全局变量
func()
print(x) # 20尽量少用 global
全局变量会让代码难以理解和维护,尽量通过参数和返回值传递数据。
nonlocal 关键字
在嵌套函数中修改外层函数的变量:
def outer():
x = 10
def inner():
nonlocal x # 声明x是外层函数的变量
x = 20
inner()
print(x) # 20
outer()14.6 嵌套函数(内部函数)
函数里面还可以定义函数:
def outer():
print("外层函数")
def inner():
print("内层函数")
inner() # 调用内层函数
outer()闭包
内部函数引用了外部函数的变量,外部函数返回内部函数:
def make_adder(n):
def adder(x):
return x + n # 引用了外部的n
return adder # 返回内部函数
add5 = make_adder(5)
print(add5(3)) # 8
print(add5(10)) # 15
add10 = make_adder(10)
print(add10(3)) # 13什么是闭包?
内部函数 + 它引用的外部变量 = 闭包 闭包可以记住外部函数的状态。
14.7 匿名函数 lambda
简单的函数可以用 lambda 一行写完。
格式
lambda 参数列表: 表达式示例
# 普通函数
def add(a, b):
return a + b
# lambda 等价写法
add = lambda a, b: a + b
print(add(3, 5)) # 8lambda 的使用场景
通常用在需要一个简单函数,且只用一次的地方:
# 1. 作为排序的key
words = ["apple", "banana", "cherry", "date"]
words.sort(key=lambda x: len(x)) # 按长度排序
# 2. 作为map/filter的参数
nums = [1, 2, 3, 4, 5]
result = map(lambda x: x * 2, nums)
# 3. 作为回调函数lambda 的限制
- 只能有一个表达式
- 不能写复杂逻辑
- 太复杂的逻辑还是用 def 定义函数
14.8 高阶函数
接收函数作为参数,或者返回函数的函数。
map()
对序列每个元素应用函数,返回新序列:
nums = [1, 2, 3, 4, 5]
# 每个元素乘2
result = map(lambda x: x * 2, nums)
print(list(result)) # [2, 4, 6, 8, 10]filter()
过滤序列,保留满足条件的元素:
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 保留偶数
result = filter(lambda x: x % 2 == 0, nums)
print(list(result)) # [2, 4, 6, 8, 10]reduce()
把序列累积成一个值(需要 import):
from functools import reduce
nums = [1, 2, 3, 4, 5]
# 求和
result = reduce(lambda a, b: a + b, nums)
print(result) # 15更 Pythonic 的方式
大多数情况下,用列表推导式比 map/filter 更清晰:
# map result = [x * 2 for x in nums] # filter result = [x for x in nums if x % 2 == 0]
14.9 递归函数
函数自己调用自己。
示例:阶乘
def factorial(n):
if n == 0 or n == 1:
return 1 # 递归出口(必须有!)
return n * factorial(n - 1)
print(factorial(5)) # 120递归的三要素
- 递归出口:什么时候停止递归(必须有,否则死循环)
- 递归公式:怎么把大问题拆成小问题
- 返回值:每次递归返回什么
注意递归深度
Python 默认递归深度约 1000 层,太深会报错。 能用循环实现的尽量用循环,效率更高。
🔗 相关章节
📝 我的笔记
在这里记录你的理解、疑问和练习代码
# 你的练习代码
✅ 本章检查清单
- 掌握函数的定义和调用
- 掌握各种参数类型(位置、默认、*args、**kwargs)
- 理解返回值和多返回值
- 会写函数文档字符串
- 理解变量作用域(局部/全局)
- 了解嵌套函数和闭包
- 会使用 lambda 匿名函数
- 了解 map/filter/reduce 高阶函数
- 理解递归函数