使用字典和字典构造函数有区别吗?

使用PyCharm,我注意到它提供了转换字典文字

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

字典构造函数

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

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

(写这个问题时,我注意到使用dict()似乎不可能指定一个数字键d = {1: 'one', 2: 'two'}是可能的,但显然, dict(1='one' ...)不是,还有别的吗?)

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

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

第二个在locals()globals()查找dict ,然后find内置的,所以你可以通过定义一个本地的被调用的dict来切换行为,虽然我想不出任何地方这是一个好主意,除了也许在debugging时

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

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

这两种方法产生相同的字典,除了你已经注意到的,Python的词汇规则干涉的地方。

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

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

dict()构造函数为您提供了更多的灵活性,因为它需要各种forms的input。 例如,您可以为它提供一个迭代器对,并将它们视为键/值对。

我不知道为什么PyCharm会提供将一种forms转换为另一种forms。

python 3.4 + pycharm的一个很大的区别是,如果键数超过了256,dict()构造函数会产生一个“语法错误”消息。

我现在更喜欢使用字典。

从python 2.7教程:

一对大括号创build一个空的字典:{}。 在大括号内放置一个以逗号分隔的键:值对列表,将初始键:值对添加到字典中; 这也是词典写在输出上的方式。

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

而:

dict()构造函数直接从存储为元组的键 – 值对列表直接构build字典。 当这些对形成一个模式时,列表推断可以紧凑地指定键值列表。

 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))) 

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

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

所以{}和dict()产生字典,但提供了一些不同的字典数据初始化方法。

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

另一方面,我已经看到人们错误字典文字为d = {'one', '1'}在现代python2.7+将创build一个集合。

尽pipe如此,我仍然喜欢全方位使用设置的文字,因为我认为它更可读,个人喜好,我想。

还要考虑这样一个事实,即与操作符匹配的令牌不能用于构造函数语法中,即dasherized键。

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

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

 class NestedDict(dict): # ... skipped state_type_map = NestedDict(**{ 'owns': 'Another', 'uses': 'Another', }) 

当你从别的东西拷贝粘贴值时,dict()文字是很好的(无Python)例如一个环境variables的列表。 如果你有一个bash文件,说

 FOO='bar' CABBAGE='good' 

你可以很容易地粘贴到一个dict()文字并添加注释。 这也使得更容易做到相反,复制到别的东西。 而{'FOO': 'bar'}语法对python和json来说是非常独特的。 因此,如果您使用json很多,您可能希望使用带有双引号的文字。