当前位置:  开发笔记 > 编程语言 > 正文

dict()和{}有什么区别?

如何解决《dict()和{}有什么区别?》经验,为你挑选了5个好方法。

所以我想说我想写一本字典.我们称之为d.但是有多种方法可以在Python中初始化字典!例如,我可以这样做:

d = {'hash': 'bang', 'slash': 'dot'}

或者我可以这样做:

d = dict(hash='bang', slash='dot')

或者,奇怪的是:

d = dict({'hash': 'bang', 'slash': 'dot'})

或这个:

d = dict([['hash', 'bang'], ['slash', 'dot']])

以及其他多种方式的dict()功能.显然,dict()提供的一件事是语法和初始化的灵活性.但这不是我要问的问题.

说我d只做一本空字典.当我做什么那张Python解释器的幕后d = {}d = dict()?它只是两种方式来做同样的事情?使用是否{}额外的电话dict()?是否有一个(甚至可以忽略不计)比另一个更多的开销?虽然这个问题真的完全不重要,但我很乐意回答这个好奇心.



1> Steven Huwig..:
>>> def f():
...     return {'a' : 1, 'b' : 2}
... 
>>> def g():
...     return dict(a=1, b=2)
... 
>>> g()
{'a': 1, 'b': 2}
>>> f()
{'a': 1, 'b': 2}
>>> import dis
>>> dis.dis(f)
  2           0 BUILD_MAP                0
              3 DUP_TOP             
              4 LOAD_CONST               1 ('a')
              7 LOAD_CONST               2 (1)
             10 ROT_THREE           
             11 STORE_SUBSCR        
             12 DUP_TOP             
             13 LOAD_CONST               3 ('b')
             16 LOAD_CONST               4 (2)
             19 ROT_THREE           
             20 STORE_SUBSCR        
             21 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('a')
              6 LOAD_CONST               2 (1)
              9 LOAD_CONST               3 ('b')
             12 LOAD_CONST               4 (2)
             15 CALL_FUNCTION          512
             18 RETURN_VALUE        

dict()显然是一些C内置的.一个非常聪明或专注的人(不是我)可以查看翻译来源并告诉你更多.我只想展示dis.dis.:)


看看Doug Hellmann的这篇好文章:http://doughellmann.com/2012/11/12/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2 html的
较新的python使`{'a':1,'b':2}更有效率.例如在python 2.7.10中,反汇编取代了`ROT_THREE; STORE_SUBSCR; 使用`STORE_MAP`进行DUP_TOP`指令.在python 3.5.1中,它将它们全部删除,只有一个`BUILD_MAP`.

2> DNS..:

就性能而言:

>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...



3> Matt Good..:

@Jacob:对象的分配方式有所不同,但它们不是写时复制.Python分配一个固定大小的"空闲列表",它可以快速分配字典对象(直到它填满).通过{}语法(或C调用PyDict_New)分配的字典可以来自此空闲列表.当字典不再被引用时,它将返回到空闲列表,并且可以重用该内存块(尽管首先重置字段).

第一个字典立即返回到空闲列表,下一个将重用其内存空间:

>>> id({})
340160
>>> id({1: 2})
340160

如果您保留引用,则下一个字典将来自下一个空闲槽:

>>> x = {}
>>> id(x)
340160
>>> id({})
340016

但我们可以删除对该字典的引用并再次释放其插槽:

>>> del x
>>> id({})
340160

由于{}语法是用字节码处理的,因此它可以使用上面提到的这种优化.另一方面dict(),像常规类构造函数一样处理,Python使用通用内存分配器,它不遵循像上面的空闲列表那样易于预测的模式.

另外,从Python 2.6查看compile.c,使用{}语法似乎根据它存储的项目数量预先调整哈希表的大小,这在解析时是已知的.



4> Benjamin Pet..:

基本上,{}是语法,在语言和字节码级别上处理.dict()只是另一种具有更灵活的初始化语法的内置函数.请注意,dict()仅添加在2.x系列的中间.



5> Jacob Gabrie..:

更新:感谢您的回复.删除了关于写时复制的猜测.

{}和之间的另一个区别dictdict总是分配一个新的字典(即使内容是静态的),{}但并不总是如此(参见mgood关于何时和为什么的答案):

def dict1():
    return {'a':'b'}

def dict2():
    return dict(a='b')

print id(dict1()), id(dict1())
print id(dict2()), id(dict2())

生产:

$ ./mumble.py
11642752 11642752
11867168 11867456

我并不是说你试图利用这个与否,这取决于具体情况,只是指出来.(如果您了解操作码,也可能从反汇编中看出来).


这不是这里发生的事情.{}仍在分配一个新的dict(否则它会非常糟糕),但是你不保持它活着这一事实意味着id可以在它死后重复使用(一旦打印出第一个dict).
推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有