当前位置: 首页 > 知识库问答 >
问题:

为什么dict.get(key)运行速度比dict[key]慢

徐峰
2023-03-14

在运行一个数字积分器时,我注意到根据我在字典中提取字段值的方式,速度有明显的不同

import numpy as np

def bad_get(mydict):
    '''Extract the name field using get()'''
    output = mydict.get('name', None)
    return output

def good_get(mydict):
    '''Extract the name field using if-else'''
    if 'name' in mydict:
        output = mydict['name']
    else:
        output = None
    return output


name_dict = dict()
name_dict['name'] = np.zeros((5000,5000))

在我的系统上,我注意到以下差异(使用 iPython)

%%timeit
bad_get(name_dict) 

The slowest run took 7.75 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 247 ns per loop

相比于

%%timeit
good_get(name_dict)  

1000000 loops, best of 3: 188 ns per loop

这似乎是一个很小的差异,但是对于某些阵列来说,这种差异甚至更大。是什么导致了这种行为,有什么方法可以改变我对< code>get()函数的使用吗?

共有1个答案

李泓
2023-03-14

Python必须为dict.get()做更多的工作:

  • get是一个属性,因此Python必须查找该属性,然后将找到的描述符绑定到字典实例
  • ()是一个调用,因此必须将当前帧推送到堆栈上,必须进行调用,然后必须从堆栈中再次弹出该帧才能继续

<代码>[...]符号,与< code>dict一起使用,不需要单独的属性步骤或帧推送和弹出。

当您使用Python字节码反汇编器< code>dis时,您可以看到不同之处:

>>> import dis
>>> dis.dis(compile('d[key]', '', 'eval'))
  1           0 LOAD_NAME                0 (d)
              3 LOAD_NAME                1 (key)
              6 BINARY_SUBSCR
              7 RETURN_VALUE
>>> dis.dis(compile('d.get(key)', '', 'eval'))
  1           0 LOAD_NAME                0 (d)
              3 LOAD_ATTR                1 (get)
              6 LOAD_NAME                2 (key)
              9 CALL_FUNCTION            1
             12 RETURN_VALUE

因此< code>d[key]表达式只需执行一个< code > BINARY _ subsr 操作码,而< code>d.get(key)则添加一个< code>LOAD_ATTR操作码。< code>CALL_FUNCTION比内置类型上的< code > BINARY _ subsr 开销大得多(带有< code>__getitem__方法的自定义类型最终仍会执行函数调用)。

如果字典中存在大部分键,则可以使用 try...除了键错误处理丢失的键:

try:
    return mydict['name']
except KeyError:
    return None

如果没有异常,异常处理很便宜。

 类似资料:
  • 这个功能有什么用处?如果我想在字典中查找与键相关联的值,我可以执行,它返回相同的内容:

  • 问题内容: 今天,我遇到了该方法,该方法在字典中给定键,然后返回关联的值。 此功能用于什么目的?如果我想找到与字典中的键相关联的值,我可以这样做,并且它返回相同的内容: 问题答案: 如果密钥丢失,它允许您提供默认值: 返回(无论您选择的是什么),而 会提出一个。 如果省略,则为,这样 返回就像

  • 问题内容: 在使用一些内置函数(如sorted,sum)时,我注意到 什么是lambda?它是如何工作的? 还有哪些其他功能使用key = lambda? 还有其他关键值吗? 问题答案: A是一个匿名函数: 它经常用在诸如以callable作为参数(通常是关键字形参)的函数中。您可以提供一个现有的函数,而不是那里的函数,只要它是一个可调用的对象即可。 以功能为例。它将以排序顺序返回给定的itera

  • 问题内容: 编辑2:有人建议,这是一个类似问题的副本。我不同意,因为我的问题集中在速度上,而另一个问题问的是什么更“可读”或“更好”(没有更好的定义)。尽管问题相似,但讨论/回答存在很大差异。 编辑:我从问题中意识到,我本可以更清楚一些。抱歉,输入错误,是的,应该使用适当的python运算符进行添加。 关于输入数据,我只是选择了一个随机数列表,因为这是一个常见的示例。在我的情况下,我使用的是我期望

  • 我最近用Java写了一个计算密集型算法,然后把它翻译成C++。令我吃惊的是,C++的执行速度要慢得多。我现在已经编写了一个更短的Java测试程序,以及一个相应的C++程序-参见下面。我的原始代码具有大量的数组访问功能,测试代码也是如此。C++的执行时间要长5.5倍(请参阅每个程序末尾的注释)。 以下1st21条评论后的结论... null null Java代码: C++代码:

  • Azure Key Vault为什么或者如何安全?我需要在服务器上存储密钥URI、客户端Id和客户端机密,因此,如果任何人授予对承载应用程序的服务器的访问权限,他将能够访问存储在密钥库中的密钥和机密。这意味着将它们存储在服务器上是一样安全的,对吗?