目录
一、递归函数
1 函数结构
递归函数通常由两个部分组成:
-
终止条件:用于确保递归能够停止,避免无限递归。
-
递归调用:函数在其内部调用自身,传递简化或减少的参数,以解决更小的子问题。
2 基本步骤
-
定义递归函数:在函数体内调用函数自身。
-
设定终止条件:确保递归能终止。
-
逐步简化问题:通过传递较小的参数递归求解,直至终止条件满足。
3 递归实例
- 阶乘定义
-
n! = n * (n-1) * (n-2) * ... * 1 -
递归公式:
n! = n * (n-1)!,终止条件:0! = 1
def factorial(n):
# 边界墙,回归条件
if n == 1 or n == 0:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
执行过程:

- 斐波那契数列:
斐波那契数列(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 Fibonacci(n):
# 边界墙:回归条件
if n < 2:
return n
return Fibonacci(n - 1) + Fibonacci(n - 2)
pass
print(Fibonacci(10)) # 55
- 列表求和
- 递归思路:将列表分为 第一个元素 和 剩余元素,总和 = 第一个元素 + 剩余元素的和。
- 终止条件:当列表为空时,和为 0。
def sum_list(lst):
# 终止条件
if not lst:
return 0
return lst[0] + sum_list(lst[1:])
print(sum_list([1, 2, 3])) # 6
二、装饰器
装饰器是Python对闭包思想的具体语法实现,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
-
日志记录:可以使用装饰器来记录函数的输入、输出或执行时间。
-
认证和授权:装饰器可以用于检查用户是否有权限执行特定操作。
-
缓存:装饰器可以缓存函数的结果,从而提高执行效率。
-
参数验证:可以使用装饰器来验证函数的输入参数是否符合预期。
-
代码注入:装饰器可以在函数的执行前后注入额外的代码。
1 基本装饰器
执行过程:
- 装饰器初始化:
decorator(say)被调用,打印…装饰器函数被调用…。decorator返回wrapper函数,say变量现在指向wrapper。
- wrapper开始执行:
- 记录开始时间并写入日志。
- 调用原始
say()函数(休眠 3 秒)。 - 记录结束时间和执行时长,写入日志。
- 返回
say()的结果'Hello World!'
后续多次使用装饰器步骤与上述一致
import time
# 装饰器函数(闭包函数) -- 可以多个地方调用,依次执行
def decorator(fn):
print('…装饰器函数被调用…')
def wrapper():
# 时间戳:1970-01-01 00:00:00 到现在(毫)秒数
start = time.time()
# 1.通用的功能装饰器,比如日志记录、执行时间记录、CPU占用记录、GPU占用记录、内存占用记录
with open('./log.txt', mode='a', encoding='utf-8') as f:
f.write(f'{fn.__name__} 模型被调用……\n')
# 2.被装饰的函数的核心功能,调用被装饰函数
sun = fn()
end = time.time()
# 1.通用的功能装饰器,比如日志记录、执行时间记录、CPU占用记录、GPU占用记录、内存占用记录
with open('./log.txt', mode='a', encoding='utf-8') as f:
f.write(f'{fn.__name__} 模型被调用……执行时间:{end - start}\n')
return sun
return wrapper
# 应用装饰器,函数say作为装饰器的实参fn运行 -- decorator(say)
@decorator
def say():
time.sleep(3) # 休眠3秒
return 'Hello World!'
# 真正调用的函数,是装饰器函数返回的函数
# 虽然调用say(),但实际上调用decorator(fn),fn指向say()
# decorator(fn)是闭包函数,外层函数返回内层函数,所以实际运行内层函数,返回也是内层函数
generator = say()
print(generator)
# deepseek大模型使用
@decorator
def DeepSeek():
return 'DeepSeek模型使用...'
generator = DeepSeek()
print(generator)
2 带参装饰器
- 三层结构
- 参数接收层(
params):接收装饰器参数(如n=2),返回真正的装饰器deep。 - 装饰器层(
deep):接收被装饰函数(如ttt),返回包装函数warp。 - 包装函数层(
warp):增强原函数功能(如记录调用次数),并调用原函数。
- 等价转换
- 调用 params(2),打印 "打印次数:2",返回 deep 函数
- 执行 deep(ttt),返回 warp 函数
- ttt 变量指向 warp
-
实际调用
warp('测试内容', temerator='0.5',high='199'):
x从 1 递增到 2。- 写入日志:
ttt,2……。 - 调用原函数
ttt('测试内容', temerator='0.5',high='199')。
-
原函数
ttt的执行:
- 遍历
kwargs。 - 返回
('测试内容',{'temerator': '0.5', 'high': '199'})。
- 返回结果
打印次数:2
('测试内容', )
# 带参装饰器
def params(n):
print(f'打印次数:{n}')
# 开始定义真正的装饰器函数
def deep(fn):
x = 1
def warp(*args, **kwargs):
nonlocal x
x += 1
with open('./demo.txt', mode='a', encoding='utf-8') as f:
f.write(f'{fn.__name__},{x}……\n')
get = fn(*args, **kwargs) # 解包操作
return get
return warp
return deep
# params(2):函数调用,返回值就是我们真正要用的装饰器函数
@params(2) # deep(ttt)
def ttt(question, **kwargs):
ff = {key: value for key, value in kwargs.items()}
return question, ff
# 真正调用的函数,是装饰器函数返回的函数
generator = ttt('测试内容', temerator='0.5', high='199')
print(generator)
3 装饰器链
实际执行 wrapper2(),其内部调用 wrapper1(),最终调用原始 hello():
-
wrapper2执行:
- 调用
fn()(即wrapper1),获取结果。 - 将结果转换为大写(
upper())。
-
wrapper1执行:
- 调用
fn()(即原始hello()),返回'Hello World!'。 - 反转结果并添加
!→'!dlroW olleH'。
-
结果传递:
wrapper1的结果'!dlroW olleH'被传递给wrapper2。wrapper2将其转换为大写 →'!DLROW OLLEH'。
def decorator1(fn):
print('装饰器1……')
print(f'装饰器1……{fn.__name__}')
def wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
return result[::-1] + '!'
return wrapper
def decorator2(fn):
print('装饰器2……')
print(f'装饰器2……{fn.__name__}')
def wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
return result.upper()
return wrapper
@decorator2 # decorator2(被decorator1装饰之后的函数)
@decorator1 # decorator1(hello)
def hello():
return 'Hello World!'
print(hello()) # !DLROW OLLEH!
今日注意!!
对于装饰器的使用通常情况下都会调用python已写好的装饰器,以上对于装饰器的解释都是便于对装饰器的理解与思考。
348

被折叠的 条评论
为什么被折叠?



