Python默认参数与关键字参数
困难3让函数更灵活:Python默认参数与关键字参数详解
在写程序时,我们经常需要让函数能处理多种情况,但又不想每次调用都写一大堆参数。Python提供了两种非常实用的参数机制——默认参数和关键字参数,它们就像点餐时的“默认套餐”和“点名点菜”,能让你的函数调用更简单、更清晰。
默认参数允许你在定义函数时给某个参数设定一个默认值,调用时如果不传这个参数,就自动使用默认值。关键字参数则允许你在调用函数时通过 参数名=值 的形式明确指定参数,这样可以不按顺序传参,代码更易读。两者常常搭配使用,让函数既灵活又安全。
为什么需要默认参数?
想象你去快餐店点餐。服务员问:“您要什么饮料?”如果你没特别说,店员会默认给你一杯可乐。但如果你喊一声“我要橙汁”,那就可以换成橙汁。这里的“可乐”就是默认选项,而“橙汁”是你特意指定的。
在Python函数里,我们也可以给参数设定一个“默认值”。这样,调用函数时如果没给这个参数,就用默认值;如果给了,就用新值。
def order_food(drink="可乐"):
print("你的套餐搭配" + drink)
order_food() # 输出:你的套餐搭配可乐
order_food("橙汁") # 输出:你的套餐搭配橙汁
生活中的更多例子:
- 计算每周零花钱:家长每周给你固定零花钱,但如果你表现好可以额外奖励。
def weekly_pocket_money(base=20, bonus=0):
# base: 基础零花钱(默认20元), bonus: 额外奖励
total = base + bonus
print("本周零花钱共", total, "元")
weekly_pocket_money() # 输出:本周零花钱共 20 元
weekly_pocket_money(bonus=5) # 输出:本周零花钱共 25 元
- 老师布置作业:默认写两页,但可以指定更多。
def assign_homework(pages=2):
print("今天作业写", pages, "页")
assign_homework() # 默认2页
assign_homework(4) # 今天作业写4页
使用默认参数可以避免重复写相同值,让函数调用更简洁,也方便后续修改默认值。
关键字参数是什么?
还是点餐的例子。服务员问:“您的主食和饮料分别要什么?”你可以说“我要汉堡,配雪碧”。但如果你记不清顺序,干脆直接说:“饮料要雪碧,主食要汉堡”。这种直接说出参数名字的方式,就是关键字参数。
在Python中,调用函数时用 参数名=值 的形式,就是关键字参数。它让我们不按顺序传参,代码更清晰。
def make_meal(main_food, drink):
print("主食:" + main_food + ",饮料:" + drink)
# 普通顺序调用
make_meal("汉堡", "雪碧")
# 关键字参数,顺序可以调换
make_meal(drink="雪碧", main_food="汉堡")
为什么用关键字参数?
- 不用记参数顺序:尤其是参数很多时,比如计算考试成绩总分的函数有
chinese, math, english,直接用math=100, chinese=90比按顺序传90,100,...更不容易搞错。 - 提高代码可读性:一看参数名就知道传的是什么值。
def report_score(chinese, math, english):
total = chinese + math + english
print("语文:", chinese, "数学:", math, "英语:", english, "总分:", total)
# 用关键字参数,一目了然
report_score(math=95, chinese=90, english=88)
注意:如果混用位置参数和关键字参数,位置参数必须放在关键字参数之前。比如report_score(90, english=88, math=95)是对的,但report_score(math=95, 90, english=88)会报错,因为位置参数90出现在关键字参数后面。
把两者结合起来
默认参数和关键字参数经常一起用。比如点餐时,主食必须选,但饮料可以默认可乐。你还可以用关键字参数只改其中一项。
def order_meal(main_food, drink="可乐", dessert=None):
print("主食:" + main_food + ",饮料:" + drink, end="")
if dessert:
print(",甜品:" + dessert)
else:
print(",无甜品")
# 只传主食,其他用默认
order_meal("薯条") # 主食:薯条,饮料:可乐,无甜品
# 传主食和饮料,用关键字指定饮料
order_meal("薯条", drink="橙汁") # 主食:薯条,饮料:橙汁,无甜品
# 传主食、饮料和甜品,全部指定
order_meal("汉堡", dessert="冰淇淋", drink="雪碧") # 顺序打乱也没关系
更贴近生活的例子: 模拟一个考试分数计算函数,总分为100分,语文、数学、英语三科,其中数学默认权重为1,其他科权重默认为1,但可以调整。
def calculate_score(chinese, math, english, weight_math=1, weight_chinese=1, weight_english=1):
# chinese, math, english: 各科原始分数
# weight_*: 各科权重,默认都是1
final = chinese * weight_chinese + math * weight_math + english * weight_english
print("加权总分:", final)
# 正常调用,全用默认权重
calculate_score(90, 80, 85) # 相当于 90*1 + 80*1 + 85*1 = 255
# 只提高数学权重
calculate_score(90, 80, 85, weight_math=1.5) # 90 + 80*1.5 + 85 = 295
# 调换关键字顺序也没问题
calculate_score(90, 80, 85, weight_english=0.8, weight_math=1.2)
新手容易犯的错误
-
默认参数写在必须参数前面
Python不允许“先写有默认值的参数,再写无默认值的参数”,因为这样会导致歧义。def wrong_example(a=1, b): # 错误!SyntaxError pass正确写法:必须参数在前,默认参数在后。
def correct_example(a, b=1): # 正确 pass -
默认参数使用可变对象(如列表、字典)
默认参数只在函数定义时被创建一次,如果默认值是一个可变对象(比如空列表),多次调用可能会共用同一个对象,导致奇怪的结果。def add_item(item, list_item=[]): list_item.append(item) return list_item print(add_item("苹果")) # ['苹果'] print(add_item("香蕉")) # ['苹果', '香蕉'] —— 不是期望的空列表解决方法是改用
None,然后在函数内部创建列表:def add_item(item, list_item=None): if list_item is None: list_item = [] list_item.append(item) return list_item -
关键字参数拼写错误
如果关键字参数名写错,Python会报TypeError,指出不认识该参数。def greet(name): print("你好", name) greet(nam="小明") # TypeError: greet() got an unexpected keyword argument 'nam' -
混用位置参数和关键字参数时顺序错误
位置参数必须全部写在关键字参数之前。记住:先位置后关键字。
完整可运行的代码示例
下面是一个模拟“周末游玩规划”的函数,包含必须参数(地点)、默认参数(人数默认2,交通方式默认“步行”)和关键字参数(可指定天数、预算)。通过不同调用方式感受灵活性。
def plan_trip(destination, people=2, transport="步行", *, days=1, budget=100):
# destination: 目的地(必须)
# people: 人数(默认2)
# transport: 交通方式(默认步行)
# days: 天数(默认1,通过*后只能关键字传参)
# budget: 预算(默认100,通过*后只能关键字传参)
total_cost = people * budget * days
print(f"周末到{destination}玩,共{people}人,交通方式:{transport},"
f"游玩{days}天,预算总费用:{total_cost}元")
# 1. 只传必须参数,其他全用默认
plan_trip("动物园")
# 输出:周末到动物园玩,共2人,交通方式:步行,游玩1天,预算总费用:200元
# 2. 传必须参数+部分默认参数(位置方式)
plan_trip("游乐园", 3, "地铁")
# 输出:周末到游乐园玩,共3人,交通方式:地铁,游玩1天,预算总费用:300元
# 3. 使用关键字参数指定天数与预算
plan_trip("博物馆", transport="公交", days=2, budget=50)
# 注意:people没改,默认2人
# 输出:周末到博物馆玩,共2人,交通方式:公交,游玩2天,预算总费用:200元
# 4. 混合使用,全部指定
plan_trip("科技馆", people=4, transport="出租车", days=1, budget=80)
# 输出:周末到科技馆玩,共4人,交通方式:出租车,游玩1天,预算总费用:320元
代码中用到了 * 来强制后面的参数只能以关键字形式传递(这是Python的另一种特性,称为仅限关键字参数),可以帮我们避免位置混淆。这里展示它是为了让你看到更复杂的参数组合,暂时了解即可。
相关指引
学完默认参数和关键字参数后,你可以继续探索以下内容:
- 可变参数:
*args和**kwargs—— 用于接收任意数量的参数,非常灵活。 - 参数传递规则:位置参数、默认参数、可变参数、关键字参数的顺序必须严格遵守,Python官方文档有详细说明。
- 函数文档:写好注释和
docstring,让函数的使用者一目了然。 - 命名规范:参数名要清晰易懂,避免用单字母(除非是临时变量)。
另外,如果你在编程中遇到“参数默认值总是被修改”的诡异问题,记得检查是否用了可变对象作为默认值,用None代替并手动初始化即可。
现在,你已经掌握了给函数参数设置“默认选项”和“点名传递”的本领。快去写几个自己的小函数练练手,比如设计一个计算游戏角色生命值的函数,或者一个统计零花钱开支的函数吧!
例题精讲
在Python函数定义中,关于默认参数的位置,以下说法正确的是?
调用函数时使用关键字参数,以下哪种说法是正确的?
在Python中,def func(x, lst=[]): 定义了一个函数,调用 func(1) 后再调用 func(2),第二次调用时 lst 的默认值仍然是空列表[]。
以下代码调用函数,需要输出 3 和 8,请使用关键字参数完成调用。
def multiply(a, b):
return a * b
result1 = multiply(1, 3) # 输出3
result2 = multiply(___) # 输出8
print(result1, result2)以下代码试图统计字符出现次数,但存在默认参数陷阱。请在划线处补全函数定义,避免该陷阱(使每次调用 count_chars 时都使用新的空列表)。
def count_chars(s, lst___):
for ch in s:
lst.append(ch)
return lst
print(count_chars("abc")) # 期望 ['a','b','c']
print(count_chars("xy")) # 期望 ['x','y'] 而不是 ['a','b','c','x','y']