上一篇:
Python:函数的位置传参、关键词传参及其可变性和解包操作-CSDN博客
目录
一、递归函数
1.1 定义
递归函数是指函数在其定义中直接或间接调用自身的一种函数。它通过将复杂问题分解为更小的同类子问题来求解。
1.2 关键特点
-
终止条件(Base Case):防止无限递归,必须存在明确的退出条件。
-
递归调用(Recursive Case):函数调用自身,逐步缩小问题规模。
-
问题简化:每次递归都使问题规模减小
1.3 基本步骤
-
定义递归函数:在函数体内调用函数自身。
-
设定终止条件:确保递归能终止。
-
逐步简化问题:通过传递较小的参数递归求解,直至终止条件满足。
1.4 经典示例
阶乘计算:
-
n! = n * (n-1) * (n-2) * ... * 1
-
递归公式:
n! = n * (n-1)!
,终止条件:0! = 1
代码示例:
def factorial(n):
# 终止条件:n为0或1时,返回1
if n == 0 or n == 1:
return 1
# 递归调用:n * (n-1)!
return n * factorial(n - 1)
# 测试
print(factorial(6)) # 输出 720
斐波那契数列:
斐波那契数列(Fibonacci sequence)是一种经典的数列,它的特点是从第 3 项开始,每一项都等于前两项之和。前两项通常定义为:
-
F(0) = 0
-
F(1) = 1
从 F(2) 开始:
-
F(2) = F(1) + F(0) = 1 + 0 = 1
-
F(3) = F(2) + F(1) = 1 + 1 = 2
使用递归的思想实现斐波那契数列,代码示例:
def fib(n):
if n == 0 or n == 1: # 终止条件
return n
return fib(n - 1) + fib(n - 2) # 递归调用
内存分配:
每次递归调用会在内存中创建新的栈帧,存储局部变量,调用结束后栈帧释放
二、装饰器
装饰器是Python对闭包思想的具体语法实现,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
-
日志记录:可以使用装饰器来记录函数的输入、输出或执行时间。
-
认证和授权:装饰器可以用于检查用户是否有权限执行特定操作。
-
缓存:装饰器可以缓存函数的结果,从而提高执行效率。
-
参数验证:可以使用装饰器来验证函数的输入参数是否符合预期。
-
代码注入:装饰器可以在函数的执行前后注入额外的代码。
装饰器是一种修改函数或类行为的语法糖,本质上是一个高阶函数(接收函数并返回新函数)。
核心思想:在不修改原函数代码的前提下,增强其功能。
2.1 闭包
2.1.1 定义
闭包必须满足以下三个条件:
-
必须有一个内嵌函数
-
内嵌函数必须引用外部函数中变量
-
外部函数返回值必须是内嵌函数
2.1.2 闭包的优缺点
优点
-
逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑。
-
方便调用上下文的局部变量。
-
加强封装性,是第2点的延伸,可以达到对变量的保护作用。
缺点
引用在,空间不灭:闭包使得函数中的变量保存在内存中,内存消耗很大
示例:
# file : closure.py
def make_power(y):
def fn(x):
return x ** y
return fn
pow2 = make_power(2)
print("5的平方是:", pow2(5))
pow3 = make_power(3)
print("6的立方是:", pow3(6))
2.2 基本装饰器
基本结构:
def decorator(func): # 外层函数接受被装饰函数
def wrapper(*args, **kwargs): # 内层包装函数
# 增强功能代码
result = func(*args, **kwargs) # 调用原函数
# 增强功能代码
return result
return wrapper # 返回包装函数
示例:
def my_decorator(func):
print("I am decorator")
def wrapper():
print("Something is happening before the function is called.")
func() # 调用传入的函数
print("Something is happening after the function is called.")
return wrapper
@my_decorator # 应用装饰器
def say_hello():
print("Hello!")
print("say_hello is:", say_hello) # 装饰器装饰之后的函数
say_hello() # 调用经过装饰器之后的函数
-
my_decorator 是一个接受一个函数 func 作为参数的装饰器。
-
wrapper 函数在被装饰函数前后添加了额外的操作。
-
使用
@my_decorator
将say_hello
函数装饰,使其在调用前后执行wrapper
中的代码。
2.3 带参装饰器
def repeat(num):
print('...函数名...()...函数执行...')
def decorator(func):
print('...装饰器...()...装饰器执行...')
def wrapper(*args, **kwargs):
for _ in range(num):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3) # 应用装饰器,重复执行下面的函数3次
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 调用被装饰的函数
-
repeat 是一个接受参数的装饰器工厂函数,它返回一个装饰器。
-
decorator 是真正的装饰器,它接受一个函数 func 作为参数。
-
wrapper 函数重复执行被装饰的函数
num
次。
2.4 装饰器链
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def exclamation(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + "!"
return wrapper
@exclamation
@uppercase
def say_hello(name):
return f"Hello, {name}"
greeting = say_hello("Bob")
print(greeting) # 输出 "HELLO, BOB!"
-
uppercase 和 exclamation 是两个装饰器,分别将文本转换为大写和添加感叹号。
-
使用
@exclamation
和@uppercase
创建装饰器链,它们按照声明的顺序依次应用。
2.5 类装饰器
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Something is happening before the function is called.")
result = self.func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
@MyDecorator # 应用类装饰器
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Charlie") # 调用被装饰的函数
-
MyDecorator 是一个类装饰器,它接受一个函数 func 作为参数并在 __call__ 方法中执行额外操作。
三、两者总结
-
递归的优雅性:适合处理树形结构(如文件遍历、XML解析)和分治算法(如快速排序)。
-
装饰器的灵活性:通过横向扩展(AOP思想)解决日志、权限等横切关注点。
-
对比:
-
递归是纵向分解问题,装饰器是横向增强功能。
-
递归需警惕性能陷阱,装饰器需注意过度嵌套导致的可读性下降。
-
-
递归:“自己调用自己,分而治之”。
-
装饰器:“穿马甲的函数,不改源码加功能”。