当前位置:首页>python>Python默认参数——让函数调用更灵活

Python默认参数——让函数调用更灵活

  • 2026-09-09 17:20:37
Python默认参数——让函数调用更灵活

一、什么是默认参数?

在定义函数时,我们可以为某些参数指定默认值。这样,在调用函数时,如果调用者没有提供该参数的值,函数就会使用默认值。这种参数称为默认参数。

默认参数让函数调用更加灵活,既可以使用默认的常见行为,也可以根据需要覆盖默认值。

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="上海"))

八、实战案例

案例1:带默认参数的欢迎函数

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=".") # 欢迎小刚.

案例2:计算商品折扣价

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(免税)

案例3:记录日志函数

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")

案例4:分页查询函数

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排序

九、最佳实践

  1. 1. 默认参数放在最后:遵循语法规则,避免定义时出错。
  2. 2. 避免使用可变对象作为默认值:使用 None 并在函数内部创建新对象。
  3. 3. 文档中说明默认值:让使用者清楚默认行为。
  4. 4. 不要过度使用默认参数:太多的默认参数会使函数复杂,考虑是否需要拆分。
  5. 5. 默认值应该是不可变的:如整数、浮点数、字符串、元组、None 等。

十、总结

  • • 默认参数 为函数参数提供默认值,使调用更灵活。
  • • 定义时必须放在位置参数之后。
  • • 默认值在函数定义时计算一次,因此可变对象作为默认值会带来共享问题,应使用 None 代替。
  • • 结合关键字参数,可以轻松覆盖任意默认参数。
  • • 合理使用默认参数能让函数更易用、更强大。

掌握默认参数,是写出高质量 Python 函数的重要一步。

最新文章

随机文章