在定义函数时,我们可以为某些参数指定默认值。这样,在调用函数时,如果调用者没有提供该参数的值,函数就会使用默认值。这种参数称为默认参数。
默认参数让函数调用更加灵活,既可以使用默认的常见行为,也可以根据需要覆盖默认值。
defgreet(name, greeting="你好"):
print(f"{greeting},{name}")
# 不提供 greeting,使用默认值
greet("小明") # 你好,小明
# 提供 greeting,覆盖默认值
greet("小红", "早上好") # 早上好,小红在函数定义时,使用 参数名=默认值 的形式为参数指定默认值。
defpower(x, n=2):
"""计算 x 的 n 次方,默认 n=2(平方)"""
return x ** n
print(power(3)) # 9(使用默认 n=2)
print(power(3, 3)) # 27(指定 n=3)
print(power(3, n=4)) # 81(关键字参数指定)注意:默认参数必须放在所有位置参数之后。即先定义没有默认值的参数,再定义有默认值的参数。
# 正确
deffunc(a, b, c=3, d=4):
pass
# 错误:默认参数不能在位置参数之前
# def func(a=1, b, c): # SyntaxError
# pass调用函数时,默认参数可以按以下方式处理:
defregister(name, age, city="北京", job="学生"):
print(f"{name},{age}岁,来自{city},职业{job}")
# 只提供位置参数,默认参数使用默认值
register("张三", 20) # 张三,20岁,来自北京,职业学生
# 覆盖部分默认参数(按位置)
register("李四", 22, "上海") # 李四,22岁,来自上海,职业学生
# 覆盖指定默认参数(关键字)
register("王五", 25, job="工程师") # 王五,25岁,来自北京,职业工程师
register("赵六", 23, city="广州", job="医生") # 赵六,23岁,来自广州,职业医生重要:默认参数的值是在函数定义时被计算并保存的,而不是每次调用时重新计算。这一点对于可变对象(如列表、字典)尤其重要。
defadd_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 同一个列表!
print(add_item(3)) # [1, 2, 3]为什么会出现这种情况?因为 lst=[] 只在定义时创建了一个空列表,之后每次调用如果没提供 lst,使用的都是同一个列表对象。
上面例子展示了默认参数为可变对象(列表)时的“陷阱”,这往往不是我们想要的行为。同样的问题也会出现在字典、集合等可变对象上。
defadd_student(name, students={}):
students[name] = True
return students
print(add_student("张三")) # {'张三': True}
print(add_student("李四")) # {'张三': True, '李四': True} ← 同一个字典!如果需要默认值为一个可变对象,通常的做法是将默认值设为 None,在函数内部判断并创建新对象。
defadd_item(item, lst=None):
if lst isNone:
lst = []
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [2] ← 新的列表,符合预期对于字典也是类似:
defadd_student(name, students=None):
if students isNone:
students = {}
students[name] = True
return students默认参数常常与关键字参数一起使用,让调用者可以灵活地只覆盖需要修改的参数。
defcreate_user(name, age=None, city="北京", email=None):
user = {"name": name}
if age:
user["age"] = age
if city:
user["city"] = city
if email:
user["email"] = email
return user
print(create_user("张三"))
print(create_user("李四", age=22, email="li@example.com"))
print(create_user("王五", city="上海"))defwelcome(name, title="", punctuation="!"):
if title:
full_name = f"{title}{name}"
else:
full_name = name
print(f"欢迎{full_name}{punctuation}")
welcome("小明") # 欢迎小明!
welcome("小红", title="博士") # 欢迎博士小红!
welcome("小刚", punctuation=".") # 欢迎小刚.defdiscount_price(price, discount=0.1, tax_rate=0.06):
"""计算折扣后含税价格"""
discounted = price * (1 - discount)
final = discounted * (1 + tax_rate)
returnround(final, 2)
print(discount_price(100)) # 95.4(默认折扣10%,税率6%)
print(discount_price(200, discount=0.2)) # 169.6(折扣20%)
print(discount_price(150, tax_rate=0)) # 135.0(免税)deflog_message(msg, level="INFO", timestamp=None):
from datetime import datetime
if timestamp isNone:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{level}] {timestamp} - {msg}")
log_message("系统启动") # [INFO] 2025-03-20 14:30:00 - 系统启动
log_message("用户登录", level="DEBUG") # [DEBUG] 2025-03-20 14:30:01 - 用户登录
log_message("错误", level="ERROR", timestamp="2025-03-20 12:00:00")deffetch_data(page=1, page_size=20, sort_by="id"):
print(f"查询第{page}页,每页{page_size}条,按{sort_by}排序")
# 模拟返回数据
return []
fetch_data() # 查询第1页,每页20条,按id排序
fetch_data(page=2, page_size=50) # 查询第2页,每页50条,按id排序
fetch_data(sort_by="name") # 查询第1页,每页20条,按name排序None 并在函数内部创建新对象。None 等。
None 代替。掌握默认参数,是写出高质量 Python 函数的重要一步。