当前位置: 首页 > news >正文

PythonTrampoline与递归优化

# Python Trampoline 与递归优化 —— 打破递归限制
# Python 不支持尾递归优化,Trampoline 模式将递归转化为循环

import sys
from functools import wraps, partial

# 1. 递归限制问题
def factorial_recursive(n):
"""普通递归阶乘,受限于调用栈深度"""
if n <= 1: return 1
return n * factorial_recursive(n - 1)

print("默认递归限制:", sys.getrecursionlimit())
try:
factorial_recursive(2000)
except RecursionError as e:
print("递归超出限制:", e)

# 2. Trampoline 基础模式
def trampoline(func):
"""蹦床函数:反复调用返回的函数直到返回非函数值"""
result = func
while callable(result):
result = result()
return result

def factorial_trampoline(n, acc=1):
"""蹦床版阶乘 —— 返回函数而非递归调用"""
if n <= 1: return acc
return lambda: factorial_trampoline(n - 1, n * acc)

print("蹦床阶乘(10):", trampoline(factorial_trampoline(10)))
print("蹦床阶乘(5000) 位数:", len(str(trampoline(factorial_trampoline(5000)))))

# 3. 通用蹦床装饰器
def trampoline_decorator(func):
"""自动将递归函数转换为栈安全版本"""
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
while callable(result):
result = result()
return result
return wrapper

@trampoline_decorator
def even(n):
"""判断偶数(相互递归)"""
return True if n == 0 else lambda: odd(n - 1)

@trampoline_decorator
def odd(n):
"""判断奇数(与 even 相互递归)"""
return False if n == 0 else lambda: even(n - 1)

print("1000 是偶数?", even(1000))
print("100000 是偶数?", even(100000)) # 栈安全

# 4. 使用 partial 实现蹦床(比 lambda 更高效)
@trampoline_decorator
def fibonacci(n, a=0, b=1):
"""斐波那契数列的蹦床版本"""
if n == 0: return a
if n == 1: return b
return partial(fibonacci, n - 1, b, a + b)

print("斐波那契(10):", fibonacci(10))
print("斐波那契(100):", fibonacci(100))

# 5. 递归转迭代(显式栈)
def tree_depth_iterative(root):
"""树的深度计算 —— 使用显式栈替代递归"""
if root is None: return 0
stack = [(root, 1)]
max_depth = 0
while stack:
node, depth = stack.pop()
if node is not None:
max_depth = max(max_depth, depth)
if hasattr(node, 'right'):
stack.append((node.right, depth + 1))
if hasattr(node, 'left'):
stack.append((node.left, depth + 1))
return max_depth

class TreeNode:
def __init__(self, v, left=None, right=None):
self.value = v; self.left = left; self.right = right

tree = TreeNode(1,
TreeNode(2, TreeNode(4)),
TreeNode(3, None, TreeNode(5, None, TreeNode(6))))
print("树深度(迭代):", tree_depth_iterative(tree))

# 6. 三种技术对比
"""
sys.setrecursionlimit() —— 临时提升限制,治标不治本
Trampoline —— 保持递归风格,但每次"弹跳"有函数调用开销
递归转迭代 —— 性能最优,但代码复杂度增加
"""
import time

def bench(desc, func):
start = time.perf_counter()
result = func()
print(f"{desc}: {result}, 耗时 {time.perf_counter()-start:.4f}s")

def fib_iterative(n):
"""迭代版斐波那契(最高效)"""
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a

bench("蹦床fib(1000)", lambda: trampoline(fibonacci(1000)))
bench("迭代fib(1000)", lambda: fib_iterative(1000))

http://www.cnnetsun.cn/news/2636758.html

相关文章:

  • 12岁少年开源离线AI助手Fusion:本地部署Gemma3与LLaVA实战指南
  • Debian 9.5 内核升级/降级保姆级教程:从查看版本到清理旧内核,一步不落
  • ESP-03编程全攻略:从Boot模式原理到实战烧录与深度排错
  • 深入理解spconv中的SparseConvTensor:从数据结构到在PyTorch中的实际使用避坑指南
  • 星穹铁道自动化工具:一键解放双手的终极解决方案
  • 从零构建无频闪LED调光器:LM317恒流源设计与PCB实战
  • 大模型小白必看:企业AI大模型应用指南,收藏不迷路!
  • 告别PyInstaller臃肿包:实测Nuitka打包FastAPI项目,体积和速度提升多少?
  • 避坑指南:重装K8S集群时,千万别乱删/etc/cni目录(附kubernetes-cni安装报错解决方案)
  • Gemini本地化不是“装个Docker”!揭秘金融级沙箱隔离、联邦提示缓存与离线微调链路(附可审计配置模板)
  • Arduino蓝牙遥控小车制作:从硬件连接到代码解析
  • 基于AT89C51ED2与DS18B20的嵌入式温度监测系统设计与实现
  • 新唐M451单片机IAP升级实战:手把手教你配置APROM和LDROM跳转(附完整代码)
  • AI文本检测实战:从TF-IDF到BERT,构建可解释的文本分类系统
  • 高阶子查询题目精炼
  • FileZilla Server安装配置避坑全记录:从用户权限到防火墙设置,一次搞定
  • Windows驱动管理终极指南:DriverStore Explorer完全解析与实用技巧
  • Arduino物联网入门:基于MQTT协议实现传感器数据稳定发布
  • 别再复制粘贴了!手把手教你用Angular+SpringBoot定制医院电子病历模板(附汉密尔顿抑郁量表实战)
  • Adams虚拟样机避坑指南:行星齿轮仿真中‘齿轮副创建失败’的3个常见原因及解决方法
  • DIY电吉他制作指南:从电磁感应原理到动手实践
  • CCPD车牌数据集转YOLOv5格式的完整脚本与避坑指南(附Python代码)
  • 5分钟从零开始:用RVC-WebUI实现专业级AI语音克隆转换
  • 告别硬核代码!在UE4里用UMG和材质轻松实现CSS级圆角按钮(附完整材质蓝图)
  • 技术深度解析:Vue3+Vite低代码平台架构与可视化编辑实现路径
  • 基于STM32的模型火箭飞控系统设计:从硬件选型到软件实现
  • Python多线程编程实战:从GIL原理到树莓派传感器数据采集
  • 微信网页版终极解决方案:3分钟让微信在浏览器中重新可用
  • 查询rownum伪列引起的sql性能问题分析
  • German-Sentiment-BERT模型架构深度解析:从BERT到情感分类的终极指南