使用dict文字和dict构造函数之间有区别吗?

时间:2011-07-07 12:29:42

标签: python pycharm

使用PyCharm,我注意到它可以转换 dict文字

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

进入 dict构造函数

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

这些不同的方法在某些重要方面有所不同吗?

(在撰写此问题时,我注意到使用dict()似乎无法指定数字键。d = {1: 'one', 2: 'two'}是可能的,但显然,dict(1='one' ...)不是。还有其他吗? )

11 个答案:

答案 0 :(得分:107)

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

第一个不需要查找dict,这应该使它更快一点

第二个在dict然后locals()中查找globals()并找到内置内容,因此您可以通过定义一个名为dict的本地来切换行为,尽管除了调试

之外,我无法想到任何地方这都是个好主意

答案 1 :(得分:48)

Literal更快,因为它使用优化的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

答案 2 :(得分:37)

它们在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

答案 3 :(得分:13)

这两种方法产生相同的字典,正如你所指出的那样,Python的词法规则会干扰。

字典文字是一个更明显的字典,你可以创建任何类型的键,但你需要引用键名。另一方面,如果出于某种原因需要,可以使用变量作为键:

a = "hello"
d = {
    a: 'hi'
    }

dict()构造函数为您提供了更多的灵活性,因为它采用了各种形式的输入。例如,您可以为它提供成对的迭代器,并将它们视为键/值对。

我不知道为什么PyCharm会将一种形式转换为另一种形式。

答案 4 :(得分:7)

与python 3.4 + pycharm的一个重大区别是dict()构造函数 产生"语法错误"如果密钥数超过256,则显示消息。

我现在更喜欢使用dict文字。

答案 5 :(得分:6)

从python 2.7教程:

  

一对括号创建一个空   字典:{}。放置一个   以逗号分隔的键列表:值   大括号内的对增加了初始值   key:对字典的值对;   这也是字典的方式   写在输出上。

tel = {'jack': 4098, 'sape': 4139}
data = {k:v for k,v in zip(xrange(10), xrange(10,20))}

虽然:

  

dict()构造函数构建   字典直接来自列表   存储为元组的键值对。什么时候   这些对形成一个模式,列表   理解可以紧凑地指定   键值列表。

tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}
data = dict((k,v) for k,v in zip(xrange(10), xrange(10,20)))
  

当键是简单的字符串时,它   有时更容易指定对   使用关键字参数:

dict(sape=4139, guido=4127, jack=4098)
>>>  {'sape': 4139, 'jack':4098, 'guido': 4127}

因此{}和dict()都会生成字典,但提供了一些不同的字典数据初始化方式。

答案 6 :(得分:2)

没有dict文字来创建dict继承的类,使用其他方法创建自定义dict类。在这种情况下,应该使用自定义dict类构造函数,例如:

class NestedDict(dict):

    # ... skipped

state_type_map = NestedDict(**{
    'owns': 'Another',
    'uses': 'Another',
})

答案 7 :(得分:1)

我发现dict文字d = {'one': '1'}更具可读性,是您的定义数据,而不是分配事物值并将它们发送到dict()构造函数。

另一方面,我看到人们将dict字面错误输入d = {'one', '1'},在现代python 2.7+中会创建一个集合。

尽管如此,我仍然更喜欢使用set literal,因为我认为它更具可读性,个人偏好。

答案 8 :(得分:0)

当你从其他东西复制粘贴值时,dict()文字是很好的(没有python) 例如,环境变量列表。 如果你有一个bash文件,请说

FOO='bar'
CABBAGE='good'

您可以轻松地将其粘贴到dict()文字中并添加评论。它还可以更容易地执行相反的操作,复制到其他内容中。而{'FOO': 'bar'}语法对于python和json来说是非常独特的。因此,如果您经常使用json,您可能希望将{}文字与双引号一起使用。

答案 9 :(得分:0)

还要考虑这样一个事实:匹配运算符的标记不能用在构造函数语法中,即标记密钥。

>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression

>>> {'foo-bar': 1}
{'foo-bar': 1}

答案 10 :(得分:0)

参加派对太晚了,但如果您有 kwargs 功能:

def foo(a=None, b=None):
    ...

然后你像这样吐出一个dict

d_1 = { 'a': 1, 'b': 2 }
d_2 = dict(a=1, b=2)

# This works
foo(**d_1)

# And this as well
foo(**d_2)

但是 d_2 可能更适合重构可能会在您的 foo 签名中更改的参数名称。因为在 d_1 中它们是字符串。