Python 中的递归、记忆和可变默认参数

2024-03-29

“Base”的意思是不只使用lru_cache。所有这些都“足够快”——我并不是在寻找最快的算法——但时间安排让我感到惊讶,所以我希望我能了解一些有关 Python 如何“工作”的知识。

简单循环(/尾递归):

def fibonacci(n):
    a, b = 0, 1
    if n in (a, b): return n
    for _ in range(n - 1):
        a, b = b, a + b
    return b

简单记忆一下:

def fibonacci(n, memo={0:0, 1:1}):
    if len(memo) <= n:
        memo[n] = fibonacci(n - 1) + fibonacci(n - 2)
    return memo[n]

使用发电机:

def fib_seq():
    a, b = 0, 1
    yield a
    yield b
    while True:
        a, b = b, a + b
        yield b

def fibonacci(n):
    return next(x for (i, x) in enumerate(fib_seq()) if i == n)

我预计第一个非常简单,是最快的。它不是。尽管存在递归和大量函数调用,但第二个是迄今为止最快的。第三个很酷,并且使用“现代”功能,但速度更慢,这令人失望。 (我很想将生成器视为在某些方面记忆化的替代方案 - 因为它们记住它们的状态 - 并且由于它们是用 C 实现的,我希望它们会更快。)

典型结果:

loop: about 140 μs
memo: about 430 ns
genr: about 250 μs

那么,谁能特别解释为什么记忆化比简单循环快一个数量级?

EDIT:

现在很清楚,我(像我之前的许多人一样)只是偶然发现了 Python可变的默认参数。这种行为解释了执行速度的实际和表面增益。


你所看到的就是记忆的全部意义。第一次调用该函数时,memo缓存为空,必须递归。但是下次您使用相同或更低的参数调用它时,答案已经在缓存中,因此它会立即返回。如果您执行数千个调用,则将第一个调用的时间分摊到所有其他调用的时间上。这就是记忆化成为如此有用的优化的原因,您只需第一次支付费用。

如果您想查看缓存新鲜时需要多长时间并且必须执行所有递归,您可以在基准测试调用中将初始缓存作为显式参数传递:

fibonacci(100, {0:0, 1:1})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的递归、记忆和可变默认参数 的相关文章

  • 如何编译Python 1.0

    出于某种反常的原因 我想尝试Python 1 0 我将如何编译它 或者更确切地说 可以使用当前编译器干净地编译的早期版本是什么 我使用的是 Mac OS X 10 5 不过因为这只是出于好奇 关于语言如何变化 所以在 Linux 虚拟机中编
  • 如何让服务器监听多个端口

    我想用同一台服务器监听 100 个不同的 TCP 端口 这是我目前正在做的事情 import socket import select def main server socket socket socket socket AF INET
  • 查找其他列表项中列表项的列表索引

    我有一个长字符串列表 我想获取与另一个列表中的字符串子字符串匹配的列表元素的索引 使用列表理解可以轻松检查列表项是否包含列表中的单个字符串 例如这个问题 https stackoverflow com questions 4843158 c
  • 在 Python 中打开文本文件时出现问题

    这看起来应该很简单 f open C Users john Desktop text txt r 但我收到此错误 Traceback most recent call last File
  • 如何模拟嵌套函数?

    我想模拟特定函数中的一些嵌套函数 tools py def cpu count def get cpu quota return int load sys fs cgroup cpu cpu cfs quota us def get cpu
  • Python 中的类位于不同的文件中吗?

    与 Java 或 php 非常相似 我习惯将类与文件分开 Python 中也是同样的情况吗 另外 我应该如何命名该文件 像classname py一样小写还是像ClassName py一样 如果我想从此类创建一个对象 我是否需要做一些特殊的
  • 使用 QtDesigner 的 pyQt 信号/槽

    我正在尝试编写一个与 QGraphicsView 交互的程序 我想在 QGraphicsView 中发生事件时收集鼠标和键盘事件 例如 如果用户单击 QGraphicsView 小部件 我将获得鼠标位置 类似的东西 我可以很容易地对其进行硬
  • AMD plaidml 与 CPU Tensorflow - 意外结果

    我目前正在运行一个简单的脚本来训练mnist数据集 通过 Tensorflow 通过我的 CPU 运行训练给了我49us sample和使用以下代码的 3e 纪元 CPU import tensorflow as tf mnist tf k
  • Pytorch CUDA 错误:没有内核映像可用于在带有 cuda 11.1 的 RTX 3090 设备上执行

    如果我运行以下命令 import torch import sys print A sys version print B torch version print C torch cuda is available print D torc
  • 枚举列表中的列表

    我有一个约会 并记录了那天发生的事件 我想枚举显示日历的日期的事件列表 我还需要能够从列表中删除事件 def command add date event calendar if date not in calendar calendar
  • 如何使用Python优化大型数据集的API调用?

    客观的 将地址列表发送到 API 并提取某些信息 例如 指示地址是否位于洪水区域的标志 Solution 适用于小数据的 Python 脚本 Problem 我想针对大输入优化当前的解决方案 如何提高 API 调用的性能 如果我有 100
  • Linux 中如何确定哪个进程正在使用某个端口

    我目前正在其默认端口上运行 RethinkDB 因为如果我将浏览器指向localhost 8080我看到 RethinkDB Web 界面 我想关闭 RethinkDB 并使用以下命令在另一个端口上重新打开它 port offset争论 然
  • 利用“写入时复制”将数据复制到 Multiprocessing.Pool() 工作进程

    我有一点multiprocessingPython 代码看起来有点像这样 import time from multiprocessing import Pool import numpy as np class MyClass objec
  • 如何使用python将下载的音频文件扩展名重命名为mp3

    目前 我正在尝试根据艺术家姓名和歌曲标题将 YouTube 音乐视频下载为音频文件 下载所有视频后 我尝试将所有音频文件从 webm 或 mp4 扩展名重命名为 mp3 但似乎我在将文件名和扩展名更改为 mp3 时遇到了一些错误 我的代码基
  • 堆和栈数据访问性能对比

    众所周知的常识是 对于大多数算法来说 在堆栈上分配和释放数据比在堆上分配和释放数据要快得多 在C 中 代码的区别就像 double foo n n vs double foo new int n n 但是 当访问和计算位于堆或堆栈上的数据时
  • Python 中字典的 enumerate()

    我知道我们用enumerate用于迭代列表 但我在字典上尝试过 但没有给出错误 CODE enumm 0 1 1 2 2 3 4 4 5 5 6 6 7 7 for i key in enumerate enumm print i key
  • 导入后属性未添加到模块中

    我做了以下实验室 vagrant ubuntu xenial test tree pack1 init py mod1 py pack2 init py mod2 py mod3 py test py 2 directories 6 fil
  • pytest - ModuleNotFoundError - python 3.6.4

    我有一个具有以下布局的项目 MANIFEST in README md init py company init py api init py auth py debug py exceptions py reporting py rest
  • 字典条目被覆盖? [复制]

    这个问题在这里已经有答案了 我发现一些输入没有存储在 Python 3 的字典中 运行这段代码 N int input How many lines of subsequent input graph for n in range N st
  • 为什么这个多处理代码会失败? [复制]

    这个问题在这里已经有答案了 def sample pass Process target sample start Process target sample start 上面的代码失败并出现错误 已尝试在当前进程之前启动新进程 进程已完成

随机推荐

  • jQuery:如何检测元素是否未被单击?

    我想知道是否可以检测某个元素是否未被单击 这是我的代码 mpElement myFeature afterDo function This if else statement has to go inside when not clicke
  • 如何在 iOS 6.1 上正确设置 GKSession(蓝牙)

    我在让 GKSession 工作时遇到问题 下面是我的代码 当按下特定按钮时执行 GKSession session if connectButtonHasBeenPressed false NSLog connectToBluetooth
  • 仅当用户启用了 JavaScript 时才使用一些 CSS

    为了让我的网页正常降级 我有一些 CSS 只有在其相应的 JavaScript 能够运行时才应该加载它们 当且仅当浏览器启用了 JavaScript 时 加载本地 CSS 的最简单方法是什么 而且它是一个相当大的 CSS 块 所以我不想编写
  • 使用 WinHttp 发布表单

    在向服务器发布帖子之前我需要添加任何标头吗 例如 目前我正在尝试以这种方式发送请求和发布数据 LPCWSTR post L name User subject Hi message Hi if WinHttpSendRequest hReq
  • 微软图表:透明度

    我想要一个具有透明背景的图表 因此 PNG 似乎是一个不错的选择 但是当我设置透明背景时 轴标签的质量急剧下降 我该如何解决 请参阅以下代码 就目前情况而言 图表具有透明背景 正如我所希望的那样 但文本质量很差 如果我注释掉两个 Color
  • 使用 Windows 窗体在脚本终止后几分钟锁定 PowerShell ISE

    我这里有一个有趣的问题 我正在创建一个日历选择器 供我们创建帐户时使用 它工作正常并且仍在进行中 但我注意到当我在 powershell ISE 中运行脚本时 几分钟后它会锁定 我可以在此之前编辑并保存代码几分钟 事件日志中没有任何内容 我
  • ng-animate :模型更改时的动画

    我创建了一个表 用户可以在其中增加和减少值 请参阅Fiddle http jsfiddle net AnandVishnu c5p39 sample code as its not allowing me to push the link
  • 面向对象的程序员如何了解数据库驱动的编程?

    我已经使用 C 和 Java 编程一年多了 并且对面向对象编程有了很好的掌握 但是我的新副项目需要数据库驱动的模型 我正在使用 C 和 Linq 这似乎是一个非常强大的工具 但我在围绕面向对象的方法设计数据库时遇到了麻烦 我的两个主要问题是
  • 引导导航栏崩溃在计算机上工作而不是在iPhone上工作

    当我将计算机屏幕大小调整到 980 像素以下时 我的固定导航栏工作正常 一旦我的屏幕达到 979 像素或更小 导航栏折叠就会启动并完美运行 然而 当我将代码推送到 Heroku 并在 iPhone 4S 上加载该网站时 我的导航栏不仅没有折
  • 在 aws 微实例上安装 redis

    我需要在亚马逊云中安装redis 我需要它作为我的 npm 模块 kue 部署 的一部分 考虑到我对 Linux 和管理的了解并不好 任何人都可以链接我的逐步教程或解释如何做到这一点 如果您启用 Amazon Linux 上存在的 Extr
  • 通过按同一个按钮来打开/关闭 MapKit 叠加?

    我有一个带有工具栏按钮的 MapView 按下该按钮时会向 MapView 添加叠加层 我想要的是按钮 IBAction 检查地图上是否已经有覆盖物 如果有 则删除 如果没有 则添加它们 我当前添加叠加层的代码如下 IBAction wat
  • JacksonFeature 破坏了 JsonIgnoreProperties

    我有这样的 pojo JsonIgnoreProperties ignoreUnknown true public class SNAPIResponse public String status public String message
  • Keras:从 ImageDataGenerator 或 Predict_generator 获取真实标签 (y_test)

    我在用ImageDataGenerator flow from directory 从目录生成批量数据 模型成功构建后 我想获得真实和预测类标签的两列数组 和model predict generator validation genera
  • 在mawk中使用strftime函数

    我正在尝试创建 AWK 脚本 该脚本将根据某种模式过滤输入文件 并使用 strftime 函数进行一些计算 2 HB 2 n print strftime Y 使用的解释器是mawk 使用此命令触发此脚本时 awk f script3 in
  • 使用curl将文件推送到GitHub存储库

    我想在 GitHub 存储库上创建 推送 新文件 而不需要git工具 因为git我的工具不可用PHP主持人 所以我做了一些研究 发现GitHub REST API https docs github com en rest 我尝试使用cur
  • 电池的最佳使用

    作为一名程序员 我可以采取哪些措施来确保我的应用程序不会占用大量资源并耗尽电池 根据您正在编写的应用程序 其中一些可能适用于您 不要使用过多的网络调用 尝试维护不经常更改的数据缓存 并且仅在上次刷新 10 秒后运行完全刷新 阻止它们向服务器
  • SQLite Swift 中有多少种方式进行 CRUD 操作?

    当我在 SQLite 中进行 CRUD 操作时 我很困惑 因为有人对我说你可以使用 FMDB 库进行 CRUD 操作 有人说 GRDB 所以 我的问题是 在 SQLite 中有多少种方法可以进行 CRUD 操作 哪种方法是正确的 我认为 G
  • 如何在 Jquery 验证中处理 html 元素 id/name 中的特殊字符?

    我有一个 HTML 表单 它在 ids 中使用特殊字符 该表单使用 JQuery 验证插件来验证用户输入 具体来说 id 包括 GUID 以下是示例代码
  • 在 Eclipse 中,Source -> Format 在“Maven Pom Editor”中被禁用

    当打开pom xml在 Eclipse 中使用 Maven Pom Editor 并切换到选项卡pom xml我无法格式化该文件 Hitting Ctrl Shift F在完全未格式化的文件中不会执行任何操作 通过上下文菜单时Source
  • Python 中的递归、记忆和可变默认参数

    Base 的意思是不只使用lru cache 所有这些都 足够快 我并不是在寻找最快的算法 但时间安排让我感到惊讶 所以我希望我能了解一些有关 Python 如何 工作 的知识 简单循环 尾递归 def fibonacci n a b 0