Python字典查找性能,get vs in

2024-03-17

这并不是过早的优化。我的用例在内部循环的最里面对字典的权利进行了双重检查,一直运行。而且,它在智力上也令人厌烦(见结果)。

这些方法中哪一种更快?

mydict = { 'hello': 'yes', 'goodbye': 'no' }
key = 'hello'

# (A)
if key in mydict:
    a = mydict[key]
    do_things(a)
else:
    handle_an_error()

# vs (B)
a = mydict.get(key,None)
if a is not None:
    do_things(a)
else:
    handle_an_error()

编辑:这些速度相同。常识告诉我,(B) 应该明显更快,因为它只有 1 次字典查找,而 2 次,但结果不同。我正在挠头。

基准测试的结果平均超过 12 次运行,其中 1/2 为命中,另一半为未命中:

doing in
switching to get
total time for IN:  0.532250006994
total time for GET:  0.480916659037
times found: 12000000
times not found: 12000000

当运行类似的一个(*10 多个循环)而没有找到密钥时,

doing in
switching to get
total time for IN:  2.35899998744
total time for GET:  4.13858334223

Why!?

(正确)代码

import time
smalldict = {}
for i in range(10):
    smalldict[str(i*4)] = str(i*18)

smalldict["8"] = "hello"

bigdict = {}
for i in range(10000):
    bigdict[str(i*100)] = str(i*4123)
bigdict["hello"] = "yes!"

timetotal = 0
totalin = 0
totalget = 0
key = "hello"
found= 0
notfound = 0

ddo = bigdict # change to smalldict for small dict gets
print 'doing in'


for r in range(12):
    start = time.time()
    a = r % 2
    for i in range(1000000):
        if a == 0:
            if str(key) in ddo:
                found = found + 1
                foo = ddo[str(key)]
            else:
                notfound = notfound + 1
                foo = "nooo"
        else:
            if 'yo' in ddo:
                found = found + 1
                foo = ddo['yo']
            else:
                notfound = notfound + 1
                foo = "nooo"
    timetotal = timetotal + (time.time() - start)

totalin = timetotal / 12.0 

print 'switching to get'
timetotal = 0
for r in range(12):
    start = time.time()
    a = r % 2
    for i in range(1000000):
        if a == 0:
            foo = ddo.get(key,None)
            if foo is not None:
                found = found + 1
            else:
                notfound = notfound + 1
                foo = "nooo"
        else:
            foo = ddo.get('yo',None)
            if foo is not None:
                found = found + 1
                notfound = notfound + 1
            else:
                notfound = notfound + 1
                foo = "oooo"
    timetotal = timetotal + (time.time() - start)

totalget = timetotal / 12

print "total time for IN: ", totalin
print 'total time for GET: ', totalget
print 'times found:', found
print 'times not found:', notfound

(原始)代码 导入时间 小字典 = {} 对于范围(10)内的 i: 小字典[str(i*4)] = str(i*18)

smalldict["8"] = "hello"

bigdict = {}
for i in range(10000):
    bigdict[str(i*100)] = str(i*4123)
bigdict["8000"] = "hello"

timetotal = 0
totalin = 0
totalget = 0
key = "hello"
found= 0
notfound = 0

ddo = bigdict # change to smalldict for small dict gets
print 'doing in'
for r in range(12):
    start = time.time()
    a = r % 2
    for i in range(10000000):
        if a == 0:
            if key in ddo:
                foo = ddo[key]
            else:
                foo = "nooo"
        else:
            if 'yo' in ddo:
                foo = ddo['yo']
            else:
                foo = "nooo"
    timetotal = timetotal + (time.time() - start)

totalin = timetotal / 12.0 

print 'switching to get'
timetotal = 0
for r in range(12):
    start = time.time()
    a = r % 2
    for i in range(10000000):
        if a == 0:
            foo = ddo.get(key,None)
            if foo is not None:
                # yaaay
                pass
            else:
                foo = "nooo"
        else:
            foo = ddo.get('yo',None)
            if foo is not None:
                #yaaay
                pass
            else:
                foo = "oooo"
    timetotal = timetotal + (time.time() - start)

totalget = timetotal / 12

print "total time for IN: ", totalin
print 'total time for GET: ', totalget

我们可以做一些更好的计时:

import timeit

d = dict.fromkeys(range(10000))

def d_get_has(d):
    return d.get(1)

def d_get_not_has(d):
    return d.get(-1)

def d_in_has(d):
    if 1 in d:
        return d[1]

def d_in_not_has(d):
    if -1 in d:
        return d[-1]


print timeit.timeit('d_get_has(d)', 'from __main__ import d, d_get_has')
print timeit.timeit('d_get_not_has(d)', 'from __main__ import d, d_get_not_has')
print timeit.timeit('d_in_has(d)', 'from __main__ import d, d_in_has')
print timeit.timeit('d_in_not_has(d)', 'from __main__ import d, d_in_not_has')

在我的计算机上,“in”变体比.get变体。这可能是因为.get是字典上的属性查找,属性查找可能与字典上的成员资格测试一样昂贵。注意in和项目查找使用dict[x]可以直接在字节码中完成,因此可以绕过正常的方法查找...

还值得指出的是,如果我只使用 pypy ,我会得到巨大的优化:-):

$ python ~/sandbox/test.py
0.169840812683
0.1732609272
0.122044086456
0.0991759300232

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

Python字典查找性能,get vs in 的相关文章

  • 如何在Python中循环并存储自变量中的值

    我对 python 很陌生 所以这听起来可能很愚蠢 我进行了搜索 但没有找到解决方案 我在 python 中有一个名为 ExcRng 的函数 我可以对该函数执行什么样的 for 循环 以便将值存储在独立变量中 我不想将它们存储在列表中 而是
  • zk 与 gwt zk 请求太多

    您好 我正在尝试比较 zk 和 gwt 的性能 在我的比较中 如果框架本身将一些代码转换为js 那么我自己无法编写任何javascript 如get 但我无法自己编写js 在以上述方式编写代码时 几乎所有在浏览器上完成的操作都会将请求发送到
  • 即使使用 .loc[row_indexer,col_indexer] = value 时也会设置 WithCopyWarning

    这是我的代码中得到的行之一SettingWithCopyWarning value1 Total Population value1 Total Population replace to replace value 4 然后我将其更改为
  • Python - 用逗号分割,跳过括号内的内容

    我需要用逗号分隔字符串 但我对这种情况有一个问题 TEXT EXAMPLE THIS IS A EXAMPLE BUT NOT WORKS FOR ME SECOND THIRD 我想拆分并得到 var 0 TEXT EXAMPLE THI
  • Pandas重置索引未生效[重复]

    这个问题在这里已经有答案了 我不确定我在哪里误入歧途 但我似乎无法重置数据帧上的索引 当我跑步时test head 我得到以下输出 正如您所看到的 数据帧是一个切片 因此索引超出范围 我想做的是重置该数据帧的索引 所以我跑test rese
  • 如果字段值在外部列表中,Django 会注释布尔值

    想象一下我有这个 Django 模型 class Letter models Model name models CharField max length 1 unique True 还有这个列表 vowels a e i o u 我想查询
  • 如何从 Dockerfile 安装 Python 3.7 和 Pip

    我正在尝试构建基于 Ubuntu 18 04 的自定义 Docker 映像 Ubuntu 预装了 Python 3 6 但我想 1 安装 Python 3 7 2 将其设置为默认 Python 版本 这样就可以使用python代替pytho
  • sudo pip install python-Levenshtein 失败,错误代码 1

    我正在尝试在 Linux 上安装 python Levenshtein 库 但每当我尝试通过以下方式安装它时 sudo pip install python Levenshtein 我收到此错误 命令 usr bin python c 导入
  • Python Kivy - 在本机网络浏览器中打开 url 的应用程序

    我尝试制作一个简单的应用程序 在单击 Screen One 上的按钮后 在 Kivy 中打开一个网页 我使用了这个主题 Python 在应用程序中直接显示网络浏览器 iframe https stackoverflow com questi
  • matplotlib matshow 标签

    我一个月前开始使用 matplotlib 所以我仍在学习 我正在尝试用 matshow 制作热图 我的代码如下 data numpy array a reshape 4 4 cax ax matshow data interpolation
  • 将 Pandas 列中的列表拆分为单独的列

    这是我在 pandas 数据框中的 特征 列 Feature Cricket 82379 Kabaddi 255 Reality 4751 Cricket 15640 Wildlife 730 LiveTV 13 Football 4129
  • 如何列出 python PDB 中的当前行?

    在 perl 调试器中 如果重复列出离开当前行的代码段 可以通过输入命令返回到当前行 点 我无法使用 python PDB 模块找到任何类似的东西 如果我list如果我自己离开当前行并想再次查看它 似乎我必须记住当前正在执行的行号 对我来说
  • Django 在选择列表更改时创建毫无意义的迁移

    我正在尝试使用可调用创建一个带有选择字段的模型 以便 Django 在选择列表更改时不会创建迁移 如中所述this https stackoverflow com questions 31788450 stop django from cr
  • 无法截取宽度为 0 的屏幕截图

    我正在尝试截取 Bootstrap 模态内元素的屏幕截图 经过一番努力 我终于想出了这段代码 driver get https enlinea sunedu gob pe driver find element by xpath div c
  • conda-env list / conda info --envs 如何查找环境?

    我一直在尝试 anaconda miniconda 因为我的用户使用随 miniconda 安装的结构生物学程序 并且作者都没有 A 考虑到可能存在其他 miniconda 应用程序 B 他们的程序将在多用户环境中使用 因此 使用 Arch
  • 如何在列表框中显示字典

    我正在尝试将字典中的键 值对显示到列表框 Key Value A 10 B 20 C 30 我想以以下格式将它们显示在列表框中 A 10 B 20 C 30 使用以下代码我已经能够将 Listbox Datasource 链接到 Dicti
  • 如何通过字符串匹配加速 pandas 行过滤?

    我经常需要过滤 pandas 数据框df by df df col name string value 并且我想加快行选择操作 有没有快速的方法可以做到这一点 例如 In 1 df mul df 3000 2000 3 reset inde
  • Scipy 稀疏 Cumsum

    假设我有一个scipy sparse csr matrix代表下面的值 0 0 1 2 0 3 0 4 1 0 0 2 0 3 4 0 我想就地计算非零值的累积和 这会将数组更改为 0 0 1 3 0 6 0 10 1 0 0 3 0 6
  • 下标:使用字符串枚举访问我的字典值

    我想做类似的事情 使用字符串枚举访问我的字典值 我试图重载字典的下标但没有成功 访问字典 let district address JsonKeys district 其中 JsonKeys 是 enum JsonKeys String c
  • 异步和协程与任务队列

    我一直在阅读有关 python 3 中的 asyncio 模块的内容 以及更广泛地了解 python 中的协程的内容 但我不明白是什么让 asyncio 成为如此出色的工具 我的感觉是 你可以用协程做的所有事情 通过使用基于多处理模块 例如

随机推荐

  • 创建位图时使用与密度无关的像素作为宽度和高度

    Bitmap createBitmap int width int height Bitmap Config config 方法只是说给它一个高度和一个宽度 没有指示这些是实际像素还是 dp 像素 我的问题 1 这些值是 dp 像素吗 2
  • 具有小数精度的格式数字字段?

    当然 我遗漏了一些非常明显的东西 我有一个精度为 2 的小数字段 但 Formtastic 仅以一位小数显示它 除非实际值有 2 位 我缺少什么 Model create table items force gt true do t t s
  • 你能让 std::shared_ptr 管理用 new T[] 分配的数组吗?

    你能做一个std shared ptr http en cppreference com w cpp memory shared ptr指向一个数组 例如 std shared ptr
  • npm:术语“npm”不被识别为 cmdlet、函数、脚本文件或可操作程序的名称

    当我检查节点 v时 一切正常并打印出来 但 npm 显示此错误 我怎样才能解决这个问题 请帮我 我搜索了很多时间并找到了解决方案 一旦安装nodejs gt 请重新启动笔记本电脑 然后设置路径 系统属性 gt 环境设置 gt C Progr
  • Git LFS 文件未推送到远程存储库

    我正在尝试使用 git LFS 将 xlsx 文件推送到远程存储库 我尝试了两种方法 使用 Sourcetree 点击菜单和使用终端服务器 两者都会产生相同的错误消息 我在 Bitbucket 中设置了一个远程存储库并设置了允许 LFS 选
  • WPF C# 类、文本框和参考,Easy(?)“当前上下文中不存在”

    我正在拔头发 我创建了一个类 employee cs 我最初在 Window1 xaml cs 上的 公共部分类 Window1 Window 中开发了这个类 当将其移动到单独的类时 我无法再引用文本框 组合框等 我该怎么办 给出的错误是
  • Python 交互式 Shell - 带有 print 的 SyntaxError [重复]

    这个问题在这里已经有答案了 我是Python新手 我在 Windows 2003 虚拟机上安装了 Python 推出Python Shell 输入以下代码 print Hello World 它立即向我吐出以下内容 语法错误 语法无效 以下
  • 哈希表 v 自平衡搜索树

    我很想知道使用自平衡树技术来存储项目比使用哈希表更重要的推理是什么 我发现哈希表无法维护插入顺序 但我始终可以在顶部使用链表来存储插入顺序序列 我发现对于少量的值 哈希函数会增加成本 但我总是可以将哈希函数与密钥一起保存以加快查找速度 我知
  • 检测何时将文本输入到文本区域并相应地更改它

    我有一个textarea用户可以在其中输入或粘贴其他人的电子邮件地址 并在按 提交 按钮后向他们发送邀请 每封电子邮件必须用逗号分隔 并且在提交表单之前有效 验证由jQuery 验证插件 http jqueryvalidation org
  • “在‘​​vue’中找不到导出‘默认’(作为‘Vue’导入)

    我是 VueJs 的初学者 这是我的第一个应用程序 import BootstrapVue from bootstrap vue import createApp from vue import App from App vue const
  • “函数”对象没有属性“tk”是什么意思?

    我目前正在开发一个程序 可以让您注册一个帐户 然后通过将详细信息写入 txt 文档并再次读取它们来再次登录 一切都工作正常 直到我添加以下内容 def login fh open usernamepassword txt r lines f
  • 在 Swift 中过滤具有多个条件和类型的对象数组

    我正在尝试在我的应用程序中进行一些复杂的过滤 但我不知道下一步该做什么 我的数据由一个字典数组组成 其中每个字典中的值可以是String Int or String let person1 String Any first name Joh
  • Onload 使输入大小适合文本长度

    我试图让 jQuery 测试 onLoad 输入框中文本的长度 并更改输入框的大小以适应 这是迄今为止我的代码尝试 emailSubject attr size this val length 我收到以下错误 this val 不是函数 我
  • Zend_Validate_Float 语言环境不适用于 hi_IN 语言环境

    在使用 hi IN 进行数字验证时 我面临以下问题 其中 Zend Locale Format isFloat 对于非单个数字和任何语言环境都可以正常工作 但不适用于单位数字和区域设置 hi IN 源代码 测试用例 foreach arra
  • 有没有办法识别 c/c++ 库的版本?

    例如 如何获取 usr lib libz a的版本 如果可以获取其他有用的信息 例如编译器 架构等 那就太好了 我想知道这一点的原因是 当我编译程序并与特定版本的 libz 链接时 gcc 总是说它忽略了我在命令行中提供的 libz gcc
  • 覆盖 require.js 中的 setTimeout

    我们在项目中使用 require js 我们需要重写设置超时时间在第 705 行 这是我们需要的代码以某种方式忽略 省略这个 setTimeout 根本 我的意思是运行它 问题是 如果我在更改版本时显式地在开源代码中更改它 代码将丢失 我应
  • 将数组传递给存储过程

    我必须将数组和字符串传递给存储过程并返回数据表 C side public DataTable fetchRequested string empID string account string refNo string orgID str
  • 可以在 Coq 的蕴涵中使用 destruct 吗?

    destruct可以用来分割and or在柯克 不过好像也可以用暗示 例如我想证明 P gt P Lemma test P P gt P Proof unfold not intro pffpf apply pffpf intro pff
  • 如何自动填写XFA(PDF)表格?

    我正在寻找一个免费选项来填写 XFA PDF 表单 我知道 iText 是一个选择 但它们的商业价格对我来说太贵了 我更喜欢完全开源的东西 有 PDFBox 但它似乎不允许将数据插入 XFA 表单 或者至少很少解释如何插入 我只需要使用文本
  • Python字典查找性能,get vs in

    这并不是过早的优化 我的用例在内部循环的最里面对字典的权利进行了双重检查 一直运行 而且 它在智力上也令人厌烦 见结果 这些方法中哪一种更快 mydict hello yes goodbye no key hello A if key in