第33集:函数参数——默认参数
学习目标
- 理解默认参数的概念
- 掌握默认参数的定义和使用
- 学会设置合适的默认值
- 了解默认参数的注意事项
一、什么是默认参数?
默认参数是在定义函数时给参数指定默认值。调用时如果不提供该参数,就使用默认值。
核心特点
- 简化调用:不需要每次都传递所有参数
- 灵活使用:可以传递参数覆盖默认值
- 向后兼容:添加新参数不影响现有调用
- 减少重复:常用的值设为默认,避免重复输入
生活类比
- 点餐时说"来杯咖啡":默认不加糖
- 如果说"来杯咖啡,加糖":覆盖默认值
- 默认参数就像"默认选项",可以修改
二、默认参数的语法
函数定义
def 函数名(参数1=默认值1, 参数2=默认值2, ...):
函数体调用方式
# 使用默认值
函数名()
# 覆盖默认值
函数名(新值1, 新值2)| 定义 | 使用默认值调用 | 覆盖默认值调用 |
|---|---|---|
def func(a=1, b=2): |
func() |
func(10, 20) |
三、基础示例
示例1:最简单的默认参数
def greet(name, message="你好!"):
"""向某人问候,默认消息是'你好!'"""
print(f"{name},{message}")
# 使用默认消息
greet("小明") # 输出:小明,你好!
# 覆盖默认消息
greet("小红", "早上好!") # 输出:小红,早上好!示例2:多个默认参数
def introduce(name, age=18, city="北京"):
"""自我介绍"""
print(f"我叫{name},{age}岁,来自{city}")
# 使用所有默认值
introduce("小王") # 输出:我叫小王,18岁,来自北京
# 覆盖部分默认值
introduce("小李", 25) # 输出:我叫小李,25岁,来自北京
# 覆盖所有默认值
introduce("小张", 30, "上海") # 输出:我叫小张,30岁,来自上海示例3:带返回值的默认参数
def power(base, exponent=2):
"""计算幂,默认计算平方"""
return base ** exponent
# 默认计算平方
print(power(5)) # 输出:25 (5²)
# 覆盖默认值,计算立方
print(power(5, 3)) # 输出:125 (5³)四、混合使用位置参数和默认参数
示例4:必需参数和默认参数混合
def calculate_price(price, quantity=1, discount=0):
"""计算最终价格"""
return price * quantity * (1 - discount)
# 只提供必需参数
result1 = calculate_price(100)
print(result1) # 输出:100
# 提供必需参数和第一个默认参数
result2 = calculate_price(100, 3)
print(result2) # 输出:300
# 提供所有参数
result3 = calculate_price(100, 3, 0.1)
print(result3) # 输出:270示例5:设置默认值的函数
def print_info(name, gender="女", age=20):
"""打印信息"""
print(f"姓名:{name},性别:{gender},年龄:{age}")
# 调用示例
print_info("小美") # 输出:姓名:小美,性别:女,年龄:20
print_info("小帅", "男") # 输出:姓名:小帅,性别:男,年龄:20
print_info("老王", "男", 45) # 输出:姓名:老王,性别:男,年龄:45五、默认参数的常见应用
示例6:登录函数
def login(username, password, remember_me=False):
"""用户登录"""
print(f"用户名:{username}")
print(f"密码:{'*' * len(password)}")
print(f"记住登录:{'是' if remember_me else '否'}")
# 不记住登录
login("user1", "123456")
# 记住登录
login("user2", "password123", remember_me=True)示例7:发送邮件函数
def send_email(to, subject, body, priority="普通", cc=None):
"""发送邮件"""
print(f"收件人:{to}")
print(f"主题:{subject}")
print(f"优先级:{priority}")
if cc:
print(f"抄送:{cc}")
print(f"内容:{body[:20]}...")
# 普通邮件
send_email("test@example.com", "测试邮件", "这是一封测试邮件")
# 重要邮件
send_email("boss@example.com", "重要通知", "项目已上线", priority="紧急")
# 带抄送的邮件
send_email("team@example.com", "会议通知", "下午3点开会", cc="manager@example.com")示例8:图形绘制函数
def draw_rectangle(width=10, height=5, char="*"):
"""绘制矩形"""
for i in range(height):
print(char * width)
# 默认矩形
print("默认矩形:")
draw_rectangle()
# 指定宽高
print("\n指定宽高的矩形:")
draw_rectangle(15, 8)
# 使用不同字符
print("\n使用#的矩形:")
draw_rectangle(12, 6, "#")六、默认参数的重要规则
规则1:默认参数必须放在位置参数之后
# ❌ 错误:默认参数在前
def greet(name="你好", message): # 报错
print(f"{name},{message}")
# ✅ 正确:默认参数在后
def greet(message, name="你好"):
print(f"{name},{message}")规则2:默认参数只计算一次(重要!)
def append_item(item, item_list=[]):
"""追加元素到列表"""
item_list.append(item)
return item_list
# ⚠️ 注意:这可能导致意外行为
print(append_item(1)) # 输出:[1]
print(append_item(2)) # 输出:[1, 2](列表被累积)
print(append_item(3)) # 输出:[1, 2, 3](列表被累积)规则3:使用None作为可变对象默认值
# ✅ 正确做法:使用None
def append_item(item, item_list=None):
"""追加元素到列表"""
if item_list is None:
item_list = []
item_list.append(item)
return item_list
# 现在每次都创建新列表
print(append_item(1)) # 输出:[1]
print(append_item(2)) # 输出:[2](新列表)
print(append_item(3)) # 输出:[3](新列表)七、实际应用案例
案例1:配置函数
def create_table(rows, columns, width=1, height=1, border="solid"):
"""创建表格"""
print(f"创建表格:{rows}行 × {columns}列")
print(f"单元格宽:{width},高:{height}")
print(f"边框样式:{border}")
# 不同配置的表格
print("简单表格:")
create_table(5, 3)
print("\n定制表格:")
create_table(10, 5, width=2, height=2, border="dashed")案例2:数据分析函数
def analyze_data(data, show_mean=True, show_median=True, show_std=False):
"""数据分析"""
n = len(data)
mean = sum(data) / n
sorted_data = sorted(data)
median = sorted_data[n // 2] if n % 2 == 1 else (sorted_data[n//2-1] + sorted_data[n//2]) / 2
std = (sum((x - mean) ** 2 for x in data) / n) ** 0.5
print(f"\n数据:{data}")
print(f"数量:{n}")
if show_mean:
print(f"均值:{mean:.2f}")
if show_median:
print(f"中位数:{median:.2f}")
if show_std:
print(f"标准差:{std:.2f}")
# 分析数据
analyze_data([1, 2, 3, 4, 5])
analyze_data([10, 20, 30, 40, 50, 60], show_std=True)
analyze_data([5, 10, 15], show_mean=False, show_median=False, show_std=True)案例3:文件操作函数
def read_file(filename, encoding="utf-8", strip_newlines=True):
"""读取文件内容"""
try:
with open(filename, 'r', encoding=encoding) as f:
content = f.read()
if strip_newlines:
content = content.strip()
return content
except FileNotFoundError:
return f"文件 {filename} 不存在"
except Exception as e:
return f"读取错误:{e}"
# 使用不同的读取方式
print("使用默认参数读取:")
print(read_file("test.txt"))
print("\n保留换行符:")
print(read_file("test.txt", strip_newlines=False))八、默认参数的最佳实践
实践1:合理设置默认值
# ✅ 好的默认值
def connect(host="localhost", port=8080, timeout=30):
"""连接服务器"""
print(f"连接到 {host}:{port},超时{timeout}秒")
# 常见的默认值
connect() # 使用所有默认值
connect("192.168.1.1") # 只修改主机
connect(port=443) # 只修改端口实践2:布尔值作为默认参数
def save_data(data, overwrite=False, backup=True):
"""保存数据"""
print(f"保存数据:{data}")
print(f"覆盖模式:{'是' if overwrite else '否'}")
print(f"创建备份:{'是' if backup else '否'}")
save_data("hello") # 不覆盖,创建备份
save_data("world", overwrite=True) # 覆盖,创建备份
save_data("test", backup=False) # 不覆盖,不创建备份实践3:枚举值作为默认参数
def sort_data(data, order="asc", algorithm="quick"):
"""排序数据"""
print(f"排序方式:{order}")
print(f"算法:{algorithm}")
sorted_data = sorted(data, reverse=(order == "desc"))
return sorted_data
# 使用不同的排序选项
result1 = sort_data([3, 1, 4, 1, 5, 9]) # 默认升序
result2 = sort_data([3, 1, 4, 1, 5, 9], order="desc") # 降序九、常见错误与调试
错误1:默认参数在位置参数之前
# ❌ 错误
def func(a=1, b): # 报错
pass
# ✅ 正确
def func(b, a=1):
pass错误2:可变对象默认值的问题
# ❌ 可能有问题
def add_item(item, items=[]):
items.append(item)
return items
# ✅ 推荐
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items调试技巧:打印参数值
def debug_func(a, b=10, c=20):
"""调试函数"""
print(f"调试信息:a={a}, b={b}, c={c}")
return a + b + c
# 调用时可以看到参数值
debug_func(5)
debug_func(5, 15)
debug_func(5, c=30)十、默认参数的优势
| 优势 | 说明 |
|---|---|
| 简化调用 | 不需要传递所有参数 |
| 提高灵活性 | 可以覆盖默认值 |
| 向后兼容 | 添加新参数不影响现有代码 |
| 减少错误 | 常用值设为默认,减少输入错误 |
| 代码清晰 | 函数意图更明确 |
十一、小结
| 知识点 | 说明 |
|---|---|
| 默认参数 | 函数定义时指定的默认值 |
| 简化调用 | 可以不传递某些参数 |
| 覆盖值 | 可以传递新值覆盖默认值 |
| 位置要求 | 默认参数必须在位置参数之后 |
| 可变注意 | 避免使用可变对象作为默认值 |
十二、课后练习
练习1
定义函数power(base, exponent=2),计算幂,默认计算平方。
练习2
定义函数create_user(username, password, role="user", active=True),创建用户信息。
练习3
定义函数format_number(num, decimals=2, currency=False),格式化数字。
练习4
定义函数send_message(content, recipient, priority="normal"),发送消息。
练习5
定义函数calculate_rectangle_area(width=10, height=10),计算矩形面积,默认是正方形。