====== 第十一章:函数基础 ======
===== 本章目标 =====
完成本章学习后,你将能够:
* 定义和调用函数
* 掌握各种参数传递方式
* 理解作用域和LEGB规则
* 使用递归解决问题
* 编写文档字符串
===== 函数定义与调用 =====
==== 基本语法 ====
# 定义函数
def greet(name):
"""问候用户"""
return f"Hello, {name}!"
# 调用函数
message = greet("Alice")
print(message) # Hello, Alice!
# 多个参数
def add(a, b):
return a + b
result = add(3, 5) # 8
# 无返回值
def print_greeting(name):
print(f"Hello, {name}!")
result = print_greeting("Bob") # None
==== 文档字符串 ====
def calculate_area(length, width):
"""
计算矩形面积。
参数:
length (float): 长度
width (float): 宽度
返回:
float: 矩形面积
示例:
>>> calculate_area(5, 3)
15
"""
return length * width
# 查看文档
print(calculate_area.__doc__)
help(calculate_area)
===== 参数类型 =====
==== 位置参数 ====
def power(base, exponent):
return base ** exponent
# 位置传参
result = power(2, 3) # 8
==== 关键字参数 ====
# 关键字传参
result = power(base=2, exponent=3)
result = power(exponent=3, base=2) # 顺序无关
# 混合使用(位置参数必须在关键字参数前)
result = power(2, exponent=3)
# power(base=2, 3) # SyntaxError
==== 默认参数 ====
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
# 默认参数的陷阱:使用可变对象
def bad_append(item, items=[]):
items.append(item)
return items
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2],不是[2]!
# 正确做法
def good_append(item, items=None):
if items is None:
items = []
items.append(item)
return items
==== 可变参数 *args ====
def sum_all(*args):
"""接收任意数量的位置参数"""
total = 0
for num in args:
total += num
return total
# 调用
print(sum_all(1, 2, 3)) # 6
print(sum_all()) # 0
print(sum_all(1, 2, 3, 4, 5)) # 15
# args是元组
print(type(args)) #
# 展开列表/元组
nums = [1, 2, 3, 4]
print(sum_all(*nums)) # 10,等同于sum_all(1, 2, 3, 4)
==== 关键字可变参数 **kwargs ====
def print_info(**kwargs):
"""接收任意数量的关键字参数"""
for key, value in kwargs.items():
print(f"{key}: {value}")
# 调用
print_info(name="Alice", age=25, city="NYC")
# kwargs是字典
print(type(kwargs)) #
# 展开字典
data = {"name": "Bob", "age": 30}
print_info(**data) # 等同于print_info(name="Bob", age=30)
==== 完整参数定义 ====
def complex_function(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2, **kwargs):
"""
pos1, pos2: 仅限位置参数(Python 3.8+)
pos_or_kwd: 位置或关键字参数
kwd1, kwd2: 仅限关键字参数
kwargs: 额外关键字参数
"""
pass
# 示例
def greet(name, /, greeting="Hello", *, punctuation="!"):
return f"{greeting}, {name}{punctuation}"
print(greet("Alice")) # Hello, Alice!
print(greet("Alice", "Hi")) # Hi, Alice!
print(greet("Alice", punctuation=".")) # Hello, Alice.
# greet(name="Alice") # TypeError: 仅限位置参数
===== 函数是对象 =====
def greet(name):
return f"Hello, {name}!"
# 函数可以赋值给变量
say_hello = greet
print(say_hello("Alice"))
# 函数可以存储在数据结构中
functions = [greet, lambda x: f"Hi, {x}!"]
for func in functions:
print(func("Bob"))
# 函数可以作为参数
def execute(func, arg):
return func(arg)
print(execute(greet, "Charlie"))
# 函数可以作为返回值
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
===== 匿名函数 lambda =====
# 基本语法
square = lambda x: x ** 2
print(square(5)) # 25
# 多参数
add = lambda x, y: x + y
print(add(2, 3)) # 5
# 常用场景:作为参数
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1]) # 按字符串排序
print(pairs) # [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
# 在map/filter/reduce中使用
nums = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, nums))
evens = list(filter(lambda x: x % 2 == 0, nums))
from functools import reduce
product = reduce(lambda x, y: x * y, nums) # 120
===== 递归函数 =====
# 阶乘
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
# 斐波那契数列(低效)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 尾递归优化(Python不支持尾递归优化)
def factorial_tail(n, acc=1):
if n <= 1:
return acc
return factorial_tail(n - 1, n * acc)
# 使用lru_cache优化
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci_fast(n):
if n <= 1:
return n
return fibonacci_fast(n - 1) + fibonacci_fast(n - 2)
print(fibonacci_fast(100)) # 瞬间完成
===== 本章练习 =====
1. **计算器函数**:实现支持加减乘除的计算器函数,使用**kwargs处理可选参数
2. **参数解析器**:编写函数解析命令行风格的参数字符串
3. **函数计时器**:编写装饰器测量函数执行时间
4. **递归练习**:实现二分查找、汉诺塔问题
5. **高阶函数**:实现自定义的map、filter、reduce
===== 本章小结 =====
本章我们学习了:
* 函数定义和调用
* 各种参数类型:位置、关键字、默认、*args、**kwargs
* 函数作为一等公民
* lambda表达式
* 递归和优化
下一章:[[python_course:chapter12|第十二章:函数高级特性]]