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

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

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变成一本空字典。当我做 d = {}d = dict()的比较时,Python 解释器的幕后发生了什么?是不是只有两种方法可以做同样的事情?使用 {}dict()附加费调用吗?一个比另一个有更多的开销(甚至可以忽略不计)吗?虽然这个问题完全不重要,但我还是很想回答这个问题。

47706 次浏览
>>> 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 内置的。一个真正聪明或专注的人(不是我)可以查看解释器源代码并告诉你更多信息。我只是想炫耀一下。:)

就表现而言:

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

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

更新 : 感谢您的回复。消除了关于书面拷贝的猜测。

{}dict的另一个不同之处是,dict总是分配一个新字典(即使内容是静态的) ,而 {}不这样做(见 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

我不是建议你利用这一点,这取决于具体情况,只是指出来。(如果你了解操作码,从 拆卸也可以看出来)。

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

第一个字典会立即返回到空闲列表,第二个字典会重用它的内存空间:

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

如果你保留一本参考书,下一本字典将来自下一个免费插槽:

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

但我们可以删除该词典的引用,重新释放它的插槽:

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

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

另外,查看 Python 2.6中的 build.c,使用 {}语法,它似乎根据它所存储的、在解析时已知的项数来预先调整散列表的大小。

Dict ()用于从可迭代文件创建字典,如:

dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )

为了创建一个空集,我们应该在它之前使用关键字集 例如 set(),它创建了一个空集,其中只有花括号可以创建一个空结构

举个例子

print isinstance({},dict)
True
print isinstance({},set)
False
print isinstance(set(),set)
True

有趣的用法:

def func(**kwargs):
for e in kwargs:
print(e)
a = 'I want to be printed'
kwargs={a:True}
func(**kwargs)
a = 'I dont want to be printed'
kwargs=dict(a=True)
func(**kwargs)

产出:

I want to be printed
a