使用字典字面量和字典构造器有区别吗?

251 投票
13 回答
171563 浏览
提问于 2025-04-16 21:01

在使用PyCharm的时候,我发现它可以把一个字典字面量转换成:

d = {
    'one': '1',
    'two': '2',
}

变成一个字典构造器

d = dict(one='1', two='2')

这两种方法有什么重要的区别吗?

(在写这个问题的时候,我注意到使用dict()似乎无法指定数字作为键……像d = {1: 'one', 2: 'two'}是可以的,但显然dict(1='one' ...)是不行的。还有其他的区别吗?)

13 个回答

42

在Python 3.2中,它们看起来几乎是一样的。

正如gnibbler所提到的,第一个方法不需要查找dict,这应该会让它稍微快一点。

>>> def literal():
...   d = {'one': 1, 'two': 2}
...
>>> def constructor():
...   d = dict(one='1', two='2')
...
>>> import dis
>>> dis.dis(literal)
  2           0 BUILD_MAP                2
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 ('one')
              9 STORE_MAP
             10 LOAD_CONST               3 (2)
             13 LOAD_CONST               4 ('two')
             16 STORE_MAP
             17 STORE_FAST               0 (d)
             20 LOAD_CONST               0 (None)
             23 RETURN_VALUE
>>> dis.dis(constructor)
  2           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('one')
              6 LOAD_CONST               2 ('1')
              9 LOAD_CONST               3 ('two')
             12 LOAD_CONST               4 ('2')
             15 CALL_FUNCTION          512
             18 STORE_FAST               0 (d)
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE
78

字面量的速度要快很多,因为它使用了优化过的 BUILD_MAP 和 STORE_MAP 操作码,而不是通用的 CALL_FUNCTION。

> python2.7 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.958 usec per loop

> python2.7 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.479 usec per loop

> python3.2 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.975 usec per loop

> python3.2 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.409 usec per loop
139

我觉得你已经指出了最明显的区别。除此之外,

第一个方法不需要去查找 dict,这可能让它稍微快一点。

第二个方法会先在 locals() 中查找 dict,然后再在 globals() 中查找,最后找到内置的 dict。所以你可以通过定义一个叫 dict 的局部变量来改变这个行为,不过我想不出有什么地方这样做是个好主意,除了可能在调试的时候。

撰写回答