Python:第9天:函数(下)—— 参数进阶、返回值、lambda和嵌套
🎯 今日目标
-
掌握位置参数和关键字参数
-
理解不定长参数:
*args和**kwargs -
学会返回多个值(元组自动打包/解包)
-
理解函数的文档字符串(docstring)
-
学会使用
lambda匿名函数 -
了解函数的嵌套
📌 一、位置参数 vs 关键字参数
1.1 位置参数
我们昨天用的就是位置参数:调用时按照定义时的顺序传递参数。
python
def introduce(name, age, city):
print(f"我叫{name},{age}岁,来自{city}")
# 按照位置传递:name="张三", age=18, city="北京"
introduce("张三", 18, "北京")
运行结果:
text
我叫张三,18岁,来自北京
1.2 关键字参数
调用时明确指定参数名 = 值,顺序可以打乱。
python
introduce(city="上海", name="李四", age=20)
运行结果:
text
我叫李四,20岁,来自上海
💡 关键字参数让代码更清晰,尤其是参数很多的时候。而且可以跳过默认参数(后面会看到)。
1.3 位置参数和关键字参数混用
规则:位置参数必须写在关键字参数前面。
python
# 正确:位置参数在前,关键字参数在后
introduce("王五", city="深圳", age=22)
# 错误:关键字参数在前,位置参数在后
# introduce(city="深圳", "王五", 22) # 报错 SyntaxError
🎯 二、默认参数值(复习 + 进阶)
默认参数在定义时赋值,调用时可以省略。
python
def greet(name, greeting="你好"):
print(f"{greeting},{name}!")
greet("张三") # 使用默认的"你好"
greet("李四", "早上好") # 覆盖默认值
greet(name="王五", greeting="晚上好") # 关键字参数方式
运行结果:
text
你好,张三! 早上好,李四! 晚上好,王五!
⚠️ 默认参数的陷阱:默认值不要用可变对象
python
# 错误示例:默认参数用列表
def add_item(item, items=[]): # 危险!
items.append(item)
return items
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['苹果', '香蕉'] —— 预期应该是 ['香蕉']
原因:默认参数在函数定义时就被创建了,之后每次调用共用同一个列表。
正确做法:用 None 作为默认值,在函数内部创建新列表。
python
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['香蕉']
📦 三、不定长参数:*args 和 **kwargs
有时候你不知道调用者会传多少个参数,这时候可以用不定长参数。
3.1 *args —— 接收任意数量的位置参数
*args 会把所有多余的位置参数打包成一个元组(tuple)。
python
def sum_all(*args):
total = 0
for num in args:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
print(sum_all()) # 0(不传参数也可以)
运行结果:
text
6 100 0
💡
*args的名字可以任意取,但约定俗成叫args(arguments 的缩写)。*才是关键符号。
3.2 **kwargs —— 接收任意数量的关键字参数
**kwargs 会把所有多余的关键字参数打包成一个字典(dict)。
python
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="张三", age=18, city="北京")
print_info(title="Python", author="Guido", year=1991)
运行结果:
text
name: 张三 age: 18 city: 北京 title: Python author: Guido year: 1991
💡
**kwargs的名字也可以任意取,kwargs是 keyword arguments 的缩写。
3.3 同时使用普通参数、*args 和 **kwargs
顺序必须是:普通参数 → *args → **kwargs
python
def mixed(name, *args, **kwargs):
print(f"姓名: {name}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")
mixed("张三", 85, 92, 78, city="北京", age=18)
运行结果:
text
姓名: 张三
args: (85, 92, 78)
kwargs: {'city': '北京', 'age': 18}
📤 四、返回多个值
Python 函数可以返回多个值,实际上是返回一个元组,Python 会自动帮你打包和解包。
python
def get_min_max(numbers):
min_val = min(numbers)
max_val = max(numbers)
return min_val, max_val # 实际上返回元组 (min_val, max_val)
# 解包接收
min_num, max_num = get_min_max([3, 1, 8, 2, 5])
print(f"最小值: {min_num}, 最大值: {max_num}")
运行结果:
text
最小值: 1, 最大值: 8
python
# 也可以直接接收整个元组 result = get_min_max([3, 1, 8, 2, 5]) print(result) # (1, 8) print(type(result)) # <class 'tuple'>
💡 这个特性非常实用:比如你想从函数中同时返回平均值和总和、或者返回状态和错误信息。
📝 五、文档字符串(docstring)
在函数内部的第一行写一段多行字符串,用来描述函数的作用、参数和返回值,方便自己和他人阅读。
python
def calculate_bmi(weight, height):
"""
计算身体质量指数(BMI)
参数:
weight: 体重(公斤)
height: 身高(米)
返回:
float: BMI 值
"""
return weight / (height ** 2)
# 查看函数的文档
help(calculate_bmi)
运行结果:
text
Help on function calculate_bmi in module __main__:
calculate_bmi(weight, height)
计算身体质量指数(BMI)
参数:
weight: 体重(公斤)
height: 身高(米)
返回:
float: BMI 值
💡 在 VS Code 中,将鼠标悬停在函数名上,会直接显示文档字符串。养成写文档的好习惯!
⚡ 六、lambda 匿名函数
6.1 什么是 lambda?
lambda 是一种没有名字的、只有一行的函数,也叫“匿名函数”。适合用在只需要临时使用、逻辑简单的场景。
语法:
python
lambda 参数列表: 表达式
等同于:
python
def 函数名(参数列表):
return 表达式
6.2 基本例子
python
# 普通函数
def add(a, b):
return a + b
# lambda 写法
add_lambda = lambda a, b: a + b
print(add(3, 5)) # 8
print(add_lambda(3, 5)) # 8
💡
lambda的表达式会自动作为返回值,不需要写return。
6.3 经典使用场景:配合 sorted() 排序
lambda 最常用在需要传入函数的场景,比如排序时指定“按什么排序”。
python
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78},
]
# 按分数升序排序
sorted_by_score = sorted(students, key=lambda student: student["score"])
for s in sorted_by_score:
print(f"{s['name']}: {s['score']}分")
运行结果:
text
王五: 78分 张三: 85分 李四: 92分
python
# 按名字长度排序 words = ["apple", "banana", "cherry", "date"] sorted_words = sorted(words, key=lambda w: len(w)) print(sorted_words) # ['date', 'apple', 'banana', 'cherry']
🪆 七、函数的嵌套
可以在函数内部再定义函数,内部函数只在外部函数内部可见。
python
def outer(name):
def inner(greeting):
print(f"{greeting},{name}!")
return inner # 把内部函数本身返回出去
# 调用外部函数,得到内部函数
f = outer("张三")
f("你好") # 输出:你好,张三!
f("早上好") # 输出:早上好,张三!
运行结果:
text
你好,张三! 早上好,张三!
💡 这种“函数返回函数”的写法是闭包(Closure)的雏形。现在了解即可,以后深入学习时会用到。
🧪 八、综合示例:学生成绩工具集
python
# 第9天综合示例:学生成绩工具集
def get_stats(scores):
"""
计算成绩统计信息
参数:
scores: 数字列表
返回:
tuple: (总分, 平均值, 最大值, 最小值)
"""
total = sum(scores)
avg = total / len(scores)
max_score = max(scores)
min_score = min(scores)
return total, avg, max_score, min_score
def filter_scores(scores, threshold=60):
"""筛选出高于 threshold 的成绩"""
return [s for s in scores if s >= threshold]
def show_students(students, **kwargs):
"""
显示学生信息,支持按条件过滤
参数:
students: 学生字典列表
**kwargs: 过滤条件,如 name="张三", score_min=80
"""
# 应用过滤条件
filtered = students
for key, value in kwargs.items():
if key == "score_min":
filtered = [s for s in filtered if s["score"] >= value]
elif key == "name":
filtered = [s for s in filtered if s["name"] == value]
# 显示结果
if not filtered:
print("没有匹配的学生")
return
print("符合条件的同学:")
for s in filtered:
print(f" {s['name']}: {s['score']}分")
# 使用示例
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78},
{"name": "赵六", "score": 55},
]
# 统计
scores = [s["score"] for s in students]
total, avg, max_s, min_s = get_stats(scores)
print(f"全班总分: {total}")
print(f"平均分: {avg:.1f}")
print(f"最高分: {max_s}")
print(f"最低分: {min_s}")
# 筛选及格同学
passed = filter_scores(scores)
print(f"及格人数: {len(passed)}")
# 条件查询
show_students(students, score_min=80)
show_students(students, name="李四")
运行结果:
text
全班总分: 310 平均分: 77.5 最高分: 92 最低分: 55 及格人数: 3 符合条件的同学: 张三: 85分 李四: 92分 王五: 78分 符合条件的同学: 李四: 92分
🐛 九、新手常见错误及解决
| 错误现象 | 错误代码示例 | 解决方法 |
|---|---|---|
| 参数顺序错误 | introduce(age=18, "张三")(关键字参数在前) | 位置参数必须在关键字参数之前 |
| 默认参数被共享 | def f(items=[]) 导致累加 | 用 items=None 代替 |
*args 和 **kwargs 位置搞反 | def f(**kwargs, *args) | 顺序必须是 *args 在前,**kwargs在后 |
忘记 lambda 只能写表达式 | lambda x: return x*2 | return 是多余的,直接写 lambda x: x*2 |
| 嵌套函数外部无法访问 | 在外部调用内部函数 | 只能通过外部函数返回内部函数来使用 |
混淆 args 和 kwargs的用途 | 用 *args 接收关键字参数 | *args 收位置参数,**kwargs 收关键字参数 |
错误演示:默认参数陷阱
python
def add_student(name, class_list=[]): # 问题在这里
class_list.append(name)
return class_list
class_a = add_student("张三")
class_b = add_student("李四")
print(class_a) # 期望 ['张三'],实际 ['张三', '李四']
print(class_b) # ['张三', '李四']
修正:
python
def add_student(name, class_list=None):
if class_list is None:
class_list = []
class_list.append(name)
return class_list
class_a = add_student("张三") # ['张三']
class_b = add_student("李四") # ['李四']
🎯 今日总结
今天你学会了:
-
位置参数和关键字参数
-
默认参数及其注意事项(可变默认值陷阱)
-
不定长参数:
*args(接收位置参数)、**kwargs(接收关键字参数) -
函数返回多个值(元组自动打包/解包)
-
文档字符串(docstring)的写法
-
lambda匿名函数及其常见用法(排序等) -
函数的嵌套
更多推荐
所有评论(0)