Python 函数进阶

10.1 可变参数

*args - 位置可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
def sum_all(*args):
return sum(args)

print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15

# args 是元组
def show_args(*args):
print(type(args)) # <class 'tuple'>
for arg in args:
print(arg)

show_args("a", "b", "c")

**kwargs - 关键字可变参数

1
2
3
4
5
6
7
8
9
10
def show_info(**kwargs):
print(type(kwargs)) # <class 'dict'>
for key, value in kwargs.items():
print(f"{key}: {value}")

show_info(name="Alice", age=25, city="Beijing")
# 输出:
# name: Alice
# age: 25
# city: Beijing

组合使用

1
2
3
4
5
6
7
8
9
10
11
12
def func(a, b, *args, **kwargs):
print(f"a: {a}")
print(f"b: {b}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")

func(1, 2, 3, 4, 5, name="Alice", age=25)
# 输出:
# a: 1
# b: 2
# args: (3, 4, 5)
# kwargs: {'name': 'Alice', 'age': 25}

10.2 参数解包

列表/元组解包

1
2
3
4
5
def add(a, b, c):
return a + b + c

numbers = [1, 2, 3]
print(add(*numbers)) # 6

字典解包

1
2
3
4
5
def introduce(name, age, city):
print(f"{name}, {age}岁, 来自{city}")

info = {"name": "Alice", "age": 25, "city": "Beijing"}
introduce(**info) # Alice, 25岁, 来自Beijing

10.3 闭包

闭包是引用了外部作用域变量的内部函数。

1
2
3
4
5
6
7
8
9
10
def outer(x):
def inner(y):
return x + y
return inner

add5 = outer(5)
add10 = outer(10)

print(add5(3)) # 8
print(add10(3)) # 13

实际应用:计数器

1
2
3
4
5
6
7
8
9
10
11
12
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter

counter1 = make_counter()
print(counter1()) # 1
print(counter1()) # 2
print(counter1()) # 3

10.4 装饰器

装饰器用于在不修改原函数的情况下增强功能。

基本装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper

@my_decorator
def say_hello():
print("Hello!")

say_hello()
# 输出:
# 函数执行前
# Hello!
# 函数执行后

带参数的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator

@repeat(3)
def greet(name):
print(f"Hello, {name}!")

greet("Alice")
# 输出 3 次: Hello, Alice!

实用装饰器示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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("执行完成")

slow_function()

10.5 递归函数

递归是函数调用自身的技术。

示例:阶乘

1
2
3
4
5
6
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)

print(factorial(5)) # 120

示例:斐波那契数列

1
2
3
4
5
6
7
8
9
def fibonacci(n):
if n <= 1:
return n
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 34

递归注意事项

  • 必须有终止条件(基线条件)
  • 避免无限递归
  • Python 默认递归深度限制为 1000
1
2
3
4
5
import sys
print(sys.getrecursionlimit()) # 1000

# 修改递归深度(谨慎使用)
sys.setrecursionlimit(2000)

10.6 生成器函数

生成器使用 yield 返回值,可以暂停和恢复执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1

counter = count_up_to(5)
print(next(counter)) # 1
print(next(counter)) # 2
print(next(counter)) # 3

# 遍历生成器
for num in count_up_to(3):
print(num) # 1, 2, 3

生成器表达式

1
2
3
4
5
6
7
8
9
# 列表推导式 vs 生成器表达式
squares_list = [x**2 for x in range(5)] # 立即创建列表
squares_gen = (x**2 for x in range(5)) # 惰性求值

print(squares_list) # [0, 1, 4, 9, 16]
print(squares_gen) # <generator object>

# 节省内存
large_gen = (x for x in range(1000000))

10.7 函数注解进阶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from typing import List, Dict, Optional

def process_data(
items: List[int],
config: Optional[Dict[str, str]] = None
) -> List[int]:
"""
处理数据列表

Args:
items: 整数列表
config: 可选的配置字典

Returns:
处理后的整数列表
"""
if config is None:
config = {}
return [x * 2 for x in items]

10.8 本章小结

  • *args 接收位置参数(元组),**kwargs 接收关键字参数(字典)
  • 闭包是引用外部变量的内部函数
  • 装饰器用于增强函数功能,使用 @ 语法
  • 递归函数调用自身,必须有终止条件
  • 生成器使用 yield,惰性求值节省内存
  • 类型提示提高代码可读性和工具支持

练习题

  1. 编写装饰器 @log,在函数执行前后打印函数名和参数
  2. 使用递归实现计算列表元素之和
  3. 编写生成器函数,生成斐波那契数列(无限)
  4. 以下代码输出什么?
    1
    2
    3
    def func(a, *args, **kwargs):
    print(args, kwargs)
    func(1, 2, 3, x=4, y=5)
ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
Python基础教程 系列
第 10/20 篇
分享: