使用 PyCharm,我注意到它提供了转换 dict 文字的功能:
d = {
'one': '1',
'two': '2',
}
进入 dict 构造函数:
d = dict(one='1', two='2')
这些不同的方法是否在某些重要方面有所不同?
(在写这个问题时,我注意到使用 dict()
似乎不可能指定数字键 .. d = {1: 'one', 2: 'two'}
是可能的,但显然 dict(1='one' ...)
不是。还有什么?)
dict()
采用键值对列表并允许命名参数,因此它可以用于创建任何类型的 dict,而不是使用您使用的语法。 pyCharm 中存在错误 (youtrack.jetbrains.net/issue/PY-2512) 也可能毫无价值,特别是因为您发现的内容已修复)。
dict(abc = 123)
构造函数生成带有字节字符串键 'abc'
的字典,如果您使用 unicode_literals
并期望字典键是 unicode u'abc'
,这可能会令人惊讶。请参阅stackoverflow.com/questions/20357210/…。
我想你已经指出了最明显的区别。除此之外,
第一个不需要查找 dict
这应该使它更快一点
第二个在 locals()
中查找 dict
,然后在 globals()
中查找内置函数,因此您可以通过定义一个名为 dict
的本地来切换行为,尽管我想不出这会是什么地方好主意,除了调试时
字面量要快得多,因为它使用优化的 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 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
$ pypy -m perf timeit -l '1000000' -n '5' -s 'i=(("a",1), ("b", 2), ("c", 3))' "{'a': 1, 'b': 2, 'c': 3}" ....... Mean +- std dev: 1.73 ns +- 0.14 ns $ pypy -m perf timeit -l '1000000' -n '5' -s 'i=(("a",1), ("b", 2), ("c", 3))' '{k:v for k,v in i}' ....... Mean +- std dev: 139 ns +- 10 ns $ pypy -m perf timeit -l '1000000' -n '5' -s 'i=(("a",1), ("b", 2), ("c", 3))' 'dict(i)' ....... Mean +- std dev: 188 ns +- 16 ns
这两种方法产生相同的字典,但正如您所指出的,Python 的词法规则会干扰。
字典文字更明显是字典,您可以创建任何类型的键,但您需要引用键名。另一方面,如果出于某种原因需要,您可以将变量用于键:
a = "hello"
d = {
a: 'hi'
}
dict()
构造函数为您提供了更大的灵活性,因为它采用多种形式的输入。例如,您可以为它提供一个对的迭代器,它会将它们视为键/值对。
我不知道为什么 PyCharm 会提供将一种形式转换为另一种形式。
来自 python 2.7 教程:
一对大括号创建一个空字典:{}。在大括号内放置一个逗号分隔的键:值对列表,将初始键:值对添加到字典中;这也是在输出上编写字典的方式。
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() 都生成字典,但提供了一些不同的字典数据初始化方式。
与 python 3.4 + pycharm 的一大区别是,如果键的数量超过 256,dict() 构造函数会产生“语法错误”消息。
我现在更喜欢使用 dict 文字。
我发现 dict 文字 d = {'one': '1'}
更具可读性,您定义数据,而不是分配事物值并将它们发送到 dict()
构造函数。
另一方面,我看到人们将 dict 文字错误地输入为 d = {'one', '1'}
,这在现代 python 2.7+ 中将创建一个集合。
尽管如此,我仍然更喜欢使用集合文字,因为我认为它更具可读性,个人偏好。
set
的字面语法。我希望有一个用于有序 dicts 的字面语法……很确定我比集合更频繁地使用它们。
当您从其他东西(无python)复制粘贴值时,dict()文字很好,例如环境变量列表。如果你有一个 bash 文件,说
FOO='bar'
CABBAGE='good'
您可以轻松地将其粘贴到 dict()
文字中并添加评论。它还可以更容易地做相反的事情,复制到其他东西中。而 {'FOO': 'bar'}
语法对于 python 和 json 来说是非常独特的。因此,如果您经常使用 json,您可能希望使用带有双引号的 {}
文字。
没有 dict 文字来创建 dict 继承的类,具有附加方法的自定义 dict 类。在这种情况下,应使用自定义 dict 类构造函数,例如:
class NestedDict(dict):
# ... skipped
state_type_map = NestedDict(**{
'owns': 'Another',
'uses': 'Another',
})
还要考虑这样一个事实,即与运算符匹配的标记不能在构造函数语法中使用,即 dasherized 键。
>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression
>>> {'foo-bar': 1}
{'foo-bar': 1}
在这里聚会超级迟到,但如果你有一个 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
中它们是字符串。
不定期副业成功案例分享
dict
可以与zip
组合以将两个并行(即相关)数组转换为单个关联映射。