全局命名空间与本地命名空间性能差异

2023-11-26

为什么在一个函数中执行一组命令:

def main():
    [do stuff]
    return something
print(main())

会倾向于跑步1.5x to 3x在 python 中执行命令比在顶层执行命令快几倍:

[do stuff]
print(something)

差异确实如此greatly取决于“do stuff”实际做了什么并且mainly关于它访问定义/使用的名称的次数。尽管代码相似,但这两种情况之间存在根本区别:

  • 在函数中,用于加载/存储名称的字节代码是通过LOAD_FAST/STORE_FAST.
  • 在顶级范围(即模块)中,执行相同的命令LOAD_NAME/STORE_NAME哪些比较迟缓。

这可以在以下情况下看到:我将使用for循环以确保多次执行对定义的变量的查找.

功能和LOAD_FAST/STORE_FAST:

我们定义了一个简单的函数,它做了一些非常愚蠢的事情:

def main():
    b = 20
    for i in range(1000000): z = 10 * b 
    return z

生成的输出dis.dis:

dis.dis(main)
# [/snipped output/]

             18 GET_ITER
        >>   19 FOR_ITER                16 (to 38)
             22 STORE_FAST               1 (i)
             25 LOAD_CONST               3 (10)
             28 LOAD_FAST                0 (b)
             31 BINARY_MULTIPLY
             32 STORE_FAST               2 (z)
             35 JUMP_ABSOLUTE           19
        >>   38 POP_BLOCK

# [/snipped output/]

这里需要注意的是LOAD_FAST/STORE_FAST偏移量处的命令28 and 32,这些用于访问b中使用的名称BINARY_MULTIPLY操作并存储z分别是名称。正如它们的字节码名称所暗示的那样,他们是快速版本 of the LOAD_*/STORE_* family.


模块和LOAD_NAME/STORE_NAME:

现在,让我们看看输出dis对于我们之前函数的模块版本:

# compile the module
m = compile(open('main.py', 'r').read(), "main", "exec")

dis.dis(m)
# [/snipped output/]

             18 GET_ITER
        >>   19 FOR_ITER                16 (to 38)
             22 STORE_NAME               2 (i)
             25 LOAD_NAME                3 (z)
             28 LOAD_NAME                0 (b)
             31 BINARY_MULTIPLY
             32 STORE_NAME               3 (z)
             35 JUMP_ABSOLUTE           19
        >>   38 POP_BLOCK

# [/snipped output/]

在这里,我们有多个电话LOAD_NAME/STORE_NAME, which,如前所述,执行的命令更慢.

在这种情况下,执行时间会有明显的差异,主要是因为Python必须评估LOAD_NAME/STORE_NAME and LOAD_FAST/STORE_FAST多次(由于for我添加了循环),因此,每次执行每个字节码的代码时都会引入开销会积累.

“作为模块”执行的计时:

start_time = time.time()
b = 20 
for i in range(1000000): z = 10 *b
print(z)
print("Time: ", time.time() - start_time)
200
Time:  0.15162253379821777

将执行计时为函数:

start_time = time.time()
print(main())
print("Time: ", time.time() - start_time)
200
Time:  0.08665871620178223 

If you time在较小的循环中range(例如for i in range(1000))您会注意到“模块”版本更快。发生这种情况是因为需要调用函数带来的开销main()比引入的更大*_FAST vs *_NAME差异。因此,这在很大程度上与完成的工作量有关。

因此,真正的罪魁祸首以及这种差异如此明显的原因是for使用循环。你一般有0有理由在脚本的顶层放置一个像这样的密集循环。将其移至函数中并避免使用全局变量,它的设计目的是提高效率。


您可以查看每个字节码执行的代码。我将链接源3.5尽管我很确定Python的版本在这里2.7差别不大。字节码评估完成于Python/ceval.c具体在功能上PyEval_EvalFrameEx:

  • LOAD_FAST source - STORE_FAST source
  • LOAD_NAME source - STORE_NAME source

正如您将看到的,*_FAST字节码只是使用 a 来获取存储/加载的值fastlocals框架对象内包含的局部符号表.

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

全局命名空间与本地命名空间性能差异 的相关文章

  • DataFrame 在函数内部修改

    我面临一个我以前从未观察到的函数内数据帧修改的问题 有没有一种方法可以处理这个问题 以便初始数据帧不被修改 def test df df tt np nan return df dff pd DataFrame data 现在 当我打印时d
  • Python的reduce()短路了吗?

    If I do result reduce operator and False 1000 得到第一个结果后它会停止吗 自从False anything False 相似地 result reduce operator or True 10
  • 如何从谷歌云存储桶读取音频文件并在datalab笔记本中使用ipd播放

    我想在数据实验室笔记本中播放我从谷歌云存储桶中读取的声音文件 这个怎么做 import numpy as np import IPython display as ipd import librosa import soundfile as
  • 如何删除 Tkinter 网格布局中的整行

    我正在尝试使用 Tkinter 进行测试应用程序 我使用网格布局管理器创建了一个表 如下所示 有两个按钮 Add row and 删除行 Add row按预期工作 我如何删除选定的行 我的想法是为每一行提供一个检查按钮 如下所示 并且可以删
  • 使用 Scipy imsave 将 Numpy 数组保存到图像时保留未更改的数据

    使用 Scipy 保存二维 Numpy 数组 单个值 时toimage or imsave像素值与 Numpy 数组中的像素值不完全匹配 相反 在某些区域 主要是边缘 图像算法似乎使用某种插值 是否有一个选项可以停止插值并保留准确的数据 例
  • 在Python中创建一个新表

    我正在尝试从数控机床中提取数据 事件每毫秒发生一次 我需要过滤掉一些用管道 分隔的变量分隔符 PuTTy exe 程序生成的日志文件 我尝试阅读熊猫 但列不在同一位置 df pd read table data log sep 日志文件的一
  • 如何使用循环将十进制转换为二进制?

    我想编写一个程序 将十进制数 0 到 9 转换为二进制数 我可以编写如何使用重复除法将十进制数转换为二进制数的代码 但是 我在创建一个以二进制格式打印十进制数字 0 到 9 的循环时遇到了麻烦 这是我的代码 number 0 remaind
  • 网页抓取 - 前往第 2 页

    如何访问数据集的第二页 无论我做什么 它都只返回第 1 页 import bs4 from urllib request import urlopen as uReq from bs4 import BeautifulSoup as sou
  • 一行Python和SQLite代码,为什么需要加“,”? [复制]

    这个问题在这里已经有答案了 c execute INSERT INTO numbers VALUES random randint 0 100 如果我将上面的代码更改为 c execute INSERT INTO numbers VALUE
  • 杂乱的扭曲连接在不干净的时尚中消失了。没有代理。已经尝试过标题

    我正在尝试抓取这个网站 https www5 apply2jobs com jupitermed ProfExt index cfm fuseaction mExternal searchJobs https www5 apply2jobs
  • Python 视频框架

    我正在寻找一个 Python 框架 它将使我能够播放视频并在该视频上绘图 用于标记目的 我尝试过 Pyglet 但这似乎效果不是特别好 在现有视频上绘图时 会出现闪烁 即使使用双缓冲和所有这些好东西 而且似乎没有办法在每帧回调期间获取视频中
  • pip 安装软件包两次

    不幸的是我无法重现它 但我们已经见过几次了 pip 将一个软件包安装两次 如果卸载第一个 第二个就会可见并且也可以被卸载 我的问题 如果一个包安装了两次 如何用 python 检查 背景 我想编写一个测试来检查这一点 devOp Updat
  • Django 接受 AM/PM 作为表单输入

    我试图弄清楚如何使用 DateTime 字段在 Django 中接受 am pm 作为时间格式 但我遇到了一些麻烦 我尝试在 forms py 文件中这样设置 pickup date time from DateTimeField inpu
  • 大型数据集上的 Sklearn-GMM

    我有一个很大的数据集 我无法将整个数据放入内存中 我想在这个数据集上拟合 GMM 我可以用吗GMM fit sklearn mixture GMM 重复小批量数据 没有理由重复贴合 只需随机采样您认为机器可以在合理时间内计算的尽可能多的数据
  • Spyder 如何在同一线程的后台运行 asyncio 事件循环(或者确实如此?)

    我已经研究 asyncio 模块 功能几天了 因为我想将它用于我的应用程序的 IO 绑定部分 并且我认为我现在对它的工作原理有一个合理的理解 或者在至少我认为我已经理解了以下内容 任一时刻 任一线程中只能运行一个异步事件循环 一旦一切都设置
  • 从另一个 python 脚本获取返回信息

    我在 Linux 上 我有一个 python 脚本 我想从另一个 python 脚本调用它 我不想将其作为模块导入 为了一层安全性 现在为了学术练习 因为我想弄清楚这一点 我实际上想让一个脚本使用 os system 或另一个类似的函数 并
  • 最小硬币找零问题——回溯

    我正在尝试用最少数量的硬币解决硬币找零问题 采用回溯法 我实际上已经完成了它 但我想添加一些选项 按其单位打印硬币数量 而不仅仅是总数 这是我下面的Python代码 def minimum coins coin list change mi
  • scipysolve_ivp() 中的访问时间步长

    我有一个常微分方程系统 正在使用 scipy 的solve ivp 函数求解 它运行良好 但我在访问每个步骤中使用的时间步时遇到问题 我知道solve ivp 将当前时间传递给用户定义的函数 但我需要使用的时间步长 而不是当前时间 为了解决
  • 在Python中从日期时间中减去秒

    我有一个 int 变量 它实际上是秒 让我们调用这个秒数X 我需要得到当前日期和时间 以日期时间格式 减去的结果X秒 Example If X是 65 当前日期是2014 06 03 15 45 00 那么我需要得到结果2014 06 03
  • 为什么用字符串和时间增量转置 DataFrame 会转换数据类型?

    这种行为对我来说似乎很奇怪 id列 字符串 在转置后转换为时间戳df如果另一列是时间增量 import pandas as pd df pd DataFrame id 00115 01222 32333 val 12 14 170 df v

随机推荐

  • 文本区域中的新行字符会增加 C# 中的文本长度

    我的 ASP NET MVC 应用程序中遇到此问题 在我的一个模型中 有一个字段 描述 该字段的数据库列设置为NVarchar 300 在我看来 我正在创建一个文本区域 如下所示 Html TextAreaFor m gt m Descri
  • 不活动后自动关闭工作簿

    我创建了一个宏 可以在一段时间不活动后关闭WB 如果我手动打开文件 它会完美工作 但如果我使用不同 WB 中的另一个宏来打开文件 它不会在设置的不活动时间后自动关闭 我用来自动关闭它的代码是 本工作簿模块 Private Sub Workb
  • 如何在两个单独的步骤中运行 MSVC 预处理器和编译器?

    我想运行 Microsoft Visual Studio 编译器cl exe不调用预处理器 这可能吗 我认为简单地编译预处理的源代码 使用 c标志 将使预处理器以无操作的方式运行 但显然情况并非如此 我做了一些基准测试 这是一个小源文件 m
  • 使用 Rails 3 中的 Devise 显示上次登录的详细信息

    我有一个 Rails 3 应用程序 它使用 Devise 进行身份验证 我想在用户管理表中显示每个用户上次登录的日期和时间 我的应用程序基于以下应用程序 https github com dannymcc rails3 base 我已阅读
  • WPF keyDown 响应时间准确度

    我正在开发一个应用程序 用户可以在其中看到某些内容 并且必须通过单击键盘上的按键来做出反应 反应时间至关重要 越准确越好 我只编写了几行代码来测试默认设置的示例应用程序 inf WPF namespace Test
  • 保存变量值并在页面刷新后检索它[重复]

    这个问题在这里已经有答案了 我将一个字符串值保存到一个变量中 我的网页在某个过程后自动重新加载 我需要知道即使在页面刷新后我是否可以获得该变量中存储的值 我使用 javascript 代码刷新我的网页window location relo
  • 在 WPF 文本块中获取段落的最佳方法是什么? (换行符?)

    我有一些带有 r n 换行符的文本 我想在 WPF 文本块中添加换行符 我尝试将 r n 替换为 不带空格 当我在 XAML 中设置 Text 属性时它起作用 但在从 C 代码隐藏中设置时似乎不起作用 那么 将 WPF 文本块中的 r n
  • mongo组查询如何保留字段

    大家 在 mongo 组查询中 结果仅显示参数中的键 如何像mysql查询组一样保留每个组中的第一个文档 例如 name age sex province city area address ddl1st 22 纯爷们 BeiJing Be
  • 使用 CSS 仅针对 Firefox

    使用条件注释 可以轻松地使用特定于浏览器的 CSS 规则来定位 Internet Explorer 有时 Gecko 引擎 Firefox 会出现问题 使用 CSS 规则仅针对 Firefox 而不是其他浏览器的最佳方法是什么 也就是说 不
  • 如何使用用户 ID 参数下载 MSI 安装程序

    我有一个 NET C 应用程序 包含在 MSI 安装程序中 myprogram exe 我有一个 PHP 网站和一个特定页面 用户可以通过链接下载该程序 我希望能够跟踪 NET 应用程序上的某些事件 例如 程序已打开 将事件发送到我的服务器
  • 返回每组一列最大值的行[重复]

    这个问题在这里已经有答案了 如果不搜索同一个表至少两次以获取最大行 然后获取该行的值 我很难做到这一点 所讨论的表相当大 因此这是不可接受的 我的桌子可能是这样的 SCORES ID ROUND SCORE 1 1 3 1 2 6 1 3
  • 是否可以在 0.0.0.0 而不是 127.0.0.1 上启动 Vault 开发服务器?

    我有一个 Hashicorp Vault 服务器在 AWS EC2 实例上运行 地址为 127 0 0 1 8200 在我的安全组的入站规则中 我启用了 TCP 8200 但是 我无法从本地计算机访问 Vault 服务器 我认为这是因为开发
  • Clojure:减少与应用

    我理解之间的概念差异reduce and apply reduce list 1 2 3 4 5 translates to 1 2 3 4 5 apply list 1 2 3 4 5 translates to 1 2 3 4 5 然而
  • 如何从MySql中的表中删除最后一条记录(有条件)

    我有一个登录时间像这样的表 id user id datetime 1 1 2011 01 17 18 51 05 2 1 2011 01 18 18 51 05 3 1 2011 01 19 18 51 05 4 2 2011 01 19
  • 获取连接到 SignalR hub 的侦听器和客户端的数量

    有没有办法找出侦听器的数量 连接到集线器的客户端 如果至少有一个客户端已连接 我正在尝试运行 启动一项任务 否则不启动它 HubName taskActionStatus public class TaskActionStatus Hub
  • 致命:不是 git 存储库:“.git”错误

    我创建了一个预提交挂钩 它获取数据库转储并将其保存在我的应用程序 文件夹下的文件中 该文件也在 git 存储库中 保存后我将文件添加到提交列表中 以下是我的预提交文件中的代码 D xampp mysql bin mysqldump u ro
  • python:用条件替换列表中的元素

    我正在尝试使用 python 执行以下操作 但出现了奇怪的行为 假设我有以下列表 x 5 4 3 2 1 现在 我正在做类似的事情 x x gt 3 3 这给出 x 5 3 3 2 1 为什么只有第二个元素发生变化 我期待着 3 3 3 2
  • VBscript 相对路径

    我正在尝试使用以下脚本 顺便说一下 它是由批处理文件调用的 在 Windows XP 中解压缩文件 strZipFile C test zip name of zip file outFolder C destination folder
  • DateTime.ParseExact FormatException 字符串未被识别为有效的日期时间

    我完全被这个难住了 据我所知 我读过的文档和其他帖子都说这应该可行 我一定错过了一些愚蠢的东西 但我就是看不到它 我收到一个 FormatException 消息 字符串未被识别为有效的日期时间 在以下代码行上 return DateTim
  • 全局命名空间与本地命名空间性能差异

    为什么在一个函数中执行一组命令 def main do stuff return something print main 会倾向于跑步1 5x to 3x在 python 中执行命令比在顶层执行命令快几倍 do stuff print s