Python函数参数(Parameters & Arguments)完全指南:从入门到避坑
1. 核心概念区分:形参与实参
在 Python 中,函数定义时括号里的变量叫形参(parameter),它是“占位符”;调用函数时实际传入的值叫实参(argument),它是“真数据”。
一句话概括:形参是“座位”,实参是“坐上去的人”。
# 定义函数时,name 是形参(占位符)
def greet(name):
print(f"Hello, {name}!")
调用函数时,"Alice" 是实参(真实数据)
greet("Alice")
关键记忆点:形参是定义时的变量名,实参是调用时的具体值。
2. 参数分类详解
2.1 位置参数(positional arguments)
按顺序一一对应传递。数量不对会报错 TypeError。
def add(a, b):
return a + b
调用时顺序必须与定义一致
print(add(3, 5)) # 3 传给了 a,5 传给了 b
关键记忆点:位置参数靠“排队顺序”匹配,少了或多了都不行。
2.2 默认参数(default arguments)
在定义时为形参赋予默认值,调用时可以省略。想象成“餐厅套餐”,默认配菜就是可乐,你也可以换成雪碧。
def order_drink(drink="可乐"):
print(f"您的饮料是:{drink}")
order_drink() # 输出:您的饮料是:可乐
order_drink("雪碧") # 输出:您的饮料是:雪碧
关键记忆点:默认参数让函数调用更灵活,但默认值只在函数定义时计算一次(警惕可变对象!)。
2.3 关键字参数(keyword arguments)
调用时用 形参名=值 传递,不依赖顺序,可读性更高。
def student_info(name, age, grade):
print(f"{name},{age}岁,{grade}年级")
关键字传参,顺序可以任意
student_info(grade="三年级", age=9, name="小明")
关键记忆点:关键字参数提高调用可读性,但必须跟在位置参数后面。
2.4 可变位置参数(*args)
用一个星号 *args 收集多余的按位置传入的实参,打包成元组。简单说,“你有多少包袱,我全给你装到一个筐里”。
def sum_all(*args):
total = 0
for num in args:
total += num
return total
print(sum_all(1, 2, 3, 4, 5)) # 输出 15
关键记忆点:*args 把任意数量的位置参数收集为元组,常用于不确定参数个数时。
2.5 可变关键字参数(**kwargs)
两个星号 **kwargs 收集多余的关键字参数,打包成字典。相当于“你把姓名、电话、地址都写在纸条上,我帮你装进字典里”。
def build_profile(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
build_profile(name="小明", age=10, hobby="编程")
关键记忆点:**kwargs 把任意数量的关键字参数收集为字典。
3. 参数组合与顺序规则
当多种参数同时出现在函数定义中时,必须严格遵守以下强制书写顺序(从前往后):
- 位置参数(普通参数)
- 默认参数
- *args
- 关键字参数(不带默认值的)
- **kwargs
综合示例:
def example(a, b=2, *args, c=10, **kwargs):
print(f"a={a}, b={b}, args={args}, c={c}, kwargs={kwargs}")
example(1, 3, 4, 5, c=20, d=30, e=40)
输出:a=1, b=3, args=(4, 5), c=20, kwargs={'d': 30, 'e': 40}
关键记忆点:参数顺序口诀——普通、默认、*args,后面跟个关键字、**kwargs。
4. 高级用法与常见陷阱
4.1 默认参数的“可变对象”陷阱
如果默认参数是列表、字典等可变对象,每次调用都会共用同一个对象,导致数据累积。来看错误与正确对比:
错误示例:
def bad_append(item, lst=[]):
lst.append(item)
return lst
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2] —— 不是期望的 [2]!
解决方案: 默认值设为 None,在函数内部创建新对象。
def good_append(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
print(good_append(1)) # [1]
print(good_append(2)) # [2]
关键记忆点:默认参数值只在定义时计算一次,可变对象要设为 None 再内部初始化。
4.2 强制位置或关键字参数(Python 3.8+)
使用 / 和 * 可以限定参数的传递方式。
/之前的参数只能按位置传递。*之后的参数只能按关键字传递。
def personal_info(name, age, /, *, city, job):
# name 和 age 必须按位置传,city 和 job 必须按关键字传
print(f"{name},{age}岁,住在{city},工作是{job}")
正确的调用:
personal_info("小红", 25, city="北京", job="教师")
错误的调用(解注释会报错):
personal_info(name="小红", age=25, city="北京", job="教师") # name 和 age 不允许关键字
关键记忆点:/ 划清“位置参数区”,* 划清“关键字参数区”。
4.3 参数解包(调用时使用 * 和 **)
可以用 * 解开序列、** 解开字典,让它们成为独立的参数。
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 相当于 add(1, 2, 3)
info = {"a": 4, "b": 5, "c": 6}
print(add(**info)) # 相当于 add(a=4, b=5, c=6)
关键记忆点:定义函数时用 * 包起来,调用时用 * 拆开,完美对称。
5. 总结对比表
| 参数类型 | 定义语法 | 调用方式 | 典型场景 |
|---|---|---|---|
| 位置参数 | def f(a, b) | 按顺序传值 | 固定数量、顺序敏感的输入 |
| 默认参数 | def f(a=10) | 位置或关键字,可省略 | 提供可选配置 |
| 关键字参数 | (调用时) name=value | 形参名=值 | 提高可读性、可选参数多的函数 |
| *args | def f(*args) | 任意多个位置值 | 数量不定的输入(如求和、打印) |
| **kwargs | def f(**kwargs) | 任意多个 key=value | 配置字典、转发参数 |
6. 课后思考题
题目一(参数顺序改错):
def demo(a=1, b, *args):
pass
上述定义会报 SyntaxError,请指出错误原因并写出正确的先后顺序。
提示:带默认值的参数必须放在非默认参数之后。
题目二(可变对象陷阱):
def add_student(name, student_list=[]):
student_list.append(name)
return student_list
class1 = add_student("张三")
class2 = add_student("李四")
print(class2) # 输出是什么?为什么?
请先预测输出,再用可变对象陷阱的知识解释原理。
更多推荐


所有评论(0)