Python函数(下)
学习目标
通过本集的学习,你将能够:
- 使用默认参数简化函数调用
- 理解可变参数的用法
- 编写递归函数
- 理解函数作为一等公民的概念
- 掌握函数的高级用法
1. 默认参数
默认参数允许在调用函数时省略某些参数,使用预定义的默认值。
1.1 基本用法
# 带默认参数的函数
def greet(name, greeting="Hello"):
"""打招呼,可自定义问候语"""
print(f"{greeting}, {name}!")
# 使用默认参数
greet("Alice") # 输出: Hello, Alice!
# 覆盖默认参数
greet("Bob", "Hi") # 输出: Hi, Bob!
greet("Charlie", "Good morning") # 输出: Good morning, Charlie!1.2 多个默认参数
def introduce(name, age=18, city="未知"):
"""介绍个人信息"""
print(f"我叫{name},今年{age}岁,来自{city}")
introduce("张三") # 使用所有默认值
introduce("李四", 25) # 覆盖age
introduce("王五", city="北京") # 只覆盖city,age用默认值
introduce("赵六", 30, "上海") # 覆盖所有参数1.3 默认参数的注意事项
# 注意:默认参数在函数定义时计算
# 避免使用可变对象作为默认参数
# 错误示例
def bad_append(item, my_list=[]):
my_list.append(item)
return my_list
print(bad_append(1)) # 输出: [1]
print(bad_append(2)) # 输出: [1, 2] (问题:列表被重用了)
print(bad_append(3)) # 输出: [1, 2, 3]
# 正确示例
def good_append(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
print(good_append(1)) # 输出: [1]
print(good_append(2)) # 输出: [2]
print(good_append(3)) # 输出: [3]2. 可变参数
可变参数允许函数接受任意数量的参数。
2.1 *args:任意数量的位置参数
# *args 收集多个参数为一个元组
def sum_all(*args):
"""计算所有参数的和"""
total = 0
for num in args:
total += num
return total
print(sum_all(1, 2)) # 输出: 3
print(sum_all(1, 2, 3, 4)) # 输出: 10
print(sum_all(10, 20, 30)) # 输出: 60
def print_args(*args):
"""打印所有参数"""
print("参数类型:", type(args))
print("参数内容:", args)
for i, arg in enumerate(args):
print(f"参数{i}: {arg}")
print_args("a", "b", "c")ASCII图:*args 的工作原理
调用: sum_all(1, 2, 3, 4)
│
▼
┌─────────────────┐
│ 1, 2, 3, 4 │
│ 打包成元组 │
│ (1, 2, 3, 4) │
└─────────────────┘
│
▼
在函数中作为 args 使用2.2 **kwargs:任意数量的关键字参数
# **kwargs 收集多个关键字参数为一个字典
def print_info(**kwargs):
"""打印关键字参数"""
print("参数类型:", type(kwargs))
print("参数内容:", kwargs)
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=25, city="北京")
def build_person(name, **kwargs):
"""构建人物信息字典"""
person = {"name": name}
for key, value in kwargs.items():
person[key] = value
return person
person1 = build_person("张三", age=30, job="工程师")
person2 = build_person("李四", age=25, city="上海", hobby="读书")
print(person1)
print(person2)2.3 混合使用
def func(a, b, *args, **kwargs):
"""混合使用各种参数"""
print("a =", a)
print("b =", b)
print("args =", args)
print("kwargs =", kwargs)
func(1, 2, 3, 4, 5, x=10, y=20)
# 输出:
# a = 1
# b = 2
# args = (3, 4, 5)
# kwargs = {'x': 10, 'y': 20}2.4 解包参数
# 使用 * 解包列表/元组
def add(a, b, c):
return a + b + c
numbers = [1, 2, 3]
print(add(*numbers)) # 等同于 add(1, 2, 3)
# 使用 ** 解包字典
def greet(name, greeting):
print(f"{greeting}, {name}!")
info = {"name": "Alice", "greeting": "Hello"}
greet(**info) # 等同于 greet(name="Alice", greeting="Hello")3. 递归函数
递归函数是调用自身的函数。
3.1 递归的基本概念
递归 = 基线条件 + 递归条件
递归调用
│
▼
f(n) ──→ f(n-1) ──→ f(n-2) ──→ ... ──→ f(1) ──→ 基线条件
│ │ │ │
└──────────┴──────────┴──────────────────┘
返回值向上传递3.2 阶乘的递归实现
def factorial(n):
"""计算阶乘(递归实现)"""
# 基线条件:0! = 1, 1! = 1
if n == 0 or n == 1:
return 1
# 递归条件:n! = n * (n-1)!
else:
return n * factorial(n - 1)
print(factorial(5)) # 输出: 120
print(factorial(0)) # 输出: 1
print(factorial(10)) # 输出: 3628800
# 非递归实现(对比)
def factorial_iterative(n):
result = 1
for i in range(1, n + 1):
result *= i
return result阶乘递归调用流程:
factorial(5)
│
├─→ 5 * factorial(4)
│ │
│ ├─→ 4 * factorial(3)
│ │ │
│ │ ├─→ 3 * factorial(2)
│ │ │ │
│ │ │ ├─→ 2 * factorial(1)
│ │ │ │ │
│ │ │ │ └─→ 1
│ │ │ │
│ │ │ └─→ 2 * 1 = 2
│ │ │
│ │ └─→ 3 * 2 = 6
│ │
│ └─→ 4 * 6 = 24
│
└─→ 5 * 24 = 1203.3 斐波那契数列的递归实现
def fibonacci(n):
"""斐波那契数列(递归实现)"""
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# 打印前10项
for i in range(10):
print(fibonacci(i), end=" ")
# 输出: 0 1 1 2 3 5 8 13 21 343.4 递归的注意事项
# Python有递归深度限制
import sys
print("默认递归深度限制:", sys.getrecursionlimit()) # 通常是 1000
# 可以修改(但不推荐)
sys.setrecursionlimit(2000)
# 递归过深会导致栈溢出
try:
factorial(2000)
except RecursionError:
print("递归深度溢出!")4. 函数作为一等公民
在Python中,函数是一等公民,可以像其他数据类型一样使用。
4.1 函数赋值给变量
def greet(name):
return f"Hello, {name}!"
# 函数赋值给变量
say_hello = greet
print(say_hello("Alice")) # 输出: Hello, Alice!4.2 函数作为参数
def add(a, b):
return a + b
def multiply(a, b):
return a * b
def apply_operation(func, x, y):
"""接受一个函数作为参数"""
return func(x, y)
print(apply_operation(add, 3, 5)) # 输出: 8
print(apply_operation(multiply, 3, 5)) # 输出: 154.3 函数作为返回值
def make_multiplier(n):
"""返回一个乘法函数"""
def multiplier(x):
return x * n
return multiplier
times2 = make_multiplier(2)
times3 = make_multiplier(3)
print(times2(5)) # 输出: 10
print(times3(5)) # 输出: 154.4 lambda 函数(匿名函数)
# 简单的lambda函数
square = lambda x: x * x
print(square(5)) # 输出: 25
# 带多个参数的lambda
add = lambda a, b: a + b
print(add(3, 5)) # 输出: 8
# 与sorted配合使用
students = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 20},
{"name": "Charlie", "age": 30}
]
# 按年龄排序
students_sorted = sorted(students, key=lambda s: s["age"])
print(students_sorted)5. 实用案例
5.1 案例1:递归实现二分查找
# binary_search.py
def binary_search(arr, target, low=0, high=None):
"""二分查找(递归实现)"""
if high is None:
high = len(arr) - 1
# 基线条件:未找到
if low > high:
return -1
mid = (low + high) // 2
# 找到目标
if arr[mid] == target:
return mid
# 目标在左半部分
elif arr[mid] > target:
return binary_search(arr, target, low, mid - 1)
# 目标在右半部分
else:
return binary_search(arr, target, mid + 1, high)
# 测试
numbers = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search(numbers, 7)) # 输出: 3
print(binary_search(numbers, 10)) # 输出: -1
print(binary_search(numbers, 1)) # 输出: 05.2 案例2:函数装饰器
# decorator.py
import time
def timer(func):
"""计时装饰器"""
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行时间: {end - start:.4f}秒")
return result
return wrapper
@timer
def slow_function():
"""一个慢函数"""
time.sleep(1)
print("函数执行完成")
@timer
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
slow_function()
print(factorial(1000))5.3 案例3:计算器(使用函数式编程)
# functional_calculator.py
def add(a, b): return a + b
def subtract(a, b): return a - b
def multiply(a, b): return a * b
def divide(a, b): return a / b if b != 0 else "错误"
# 操作字典
operations = {
"+": add,
"-": subtract,
"*": multiply,
"/": divide
}
def calculator():
print("函数式计算器")
print("可用操作:", ", ".join(operations.keys()))
while True:
expr = input("请输入表达式 (如 3 + 5,输入 q 退出): ")
if expr.lower() == 'q':
break
try:
a, op, b = expr.split()
a = float(a)
b = float(b)
if op in operations:
result = operations[op](a, b)
print(f"结果: {result}")
else:
print("未知操作符")
except:
print("输入格式错误,请重试")
calculator()6. 自测问题
- 默认参数的值在什么时候计算?
- *args 和 **kwargs 的区别是什么?
- 递归函数必须包含什么?
- 什么是函数作为一等公民?
- lambda 函数的特点是什么?
7. 下集预告
下一集我们将学习Python的列表与元组!
参考资料
- Python官方文档: https://docs.python.org/3/tutorial/controlflow.html#more-on-defining-functions
- 《Python编程:从入门到实践》