初始化字典时,使用哪种语法更好:花括号({})还是dict()函数?

267

我正在努力学习Python,并密切关注常见的编码标准。这个问题可能看起来是无意义的吹毛求疵,但我正试图专注于最佳实践,以便在学习过程中不必纠正任何“不良”习惯。

我看到有两种常见的方法来初始化字典:

a = {
    'a': 'value',
    'another': 'value',
}

b = dict( 
    a='value',
    another='value',
)

哪一种被认为是“更符合Python风格”?你使用哪种?为什么?


5
你用的是哪个教程?你看到了哪些引起困惑的例子? - S.Lott
2
嗯,我一直在使用Python教程《Dive into Python》以及各种博客、Stack Overflow贴子和其他谷歌资源。官方文档普遍使用{},但我在其他地方看到了很多明确的dict()方法。我可以看出有明确语法的好处,但官方文档中缺少这种方法让我感到怀疑。在发布这篇文章后,我查看了dict库的文档,并发现当使用显式dict初始化字典时,键必须是有效的标识符的警告。 - daotoad
3
“dict()”比“{}”更明确的原因是因为前者显式地调用了一个内置函数来创建一个字典,而后者则是通过一对大括号实现。不理解你的困惑。在我看来,两者都很明确。你能提供一个引文或参考来支持你认为“dict”显式而“{}”不显式的说法吗?你认为这种区分来自哪里? - S.Lott
23
区别在于拼写。dict()的拼写是dict,它使用类型的名称。花括号({})依靠标点符号来识别类型。 - daotoad
7个回答

292

花括号。虽然在很多场景下,将关键字参数传递到 dict() 中可以完美地工作,但只有在键是有效的 Python 标识符时才能初始化映射。

以下代码有效:

a = {'import': 'trade', 1: 7.8}

a = dict({'import': 'trade', 1: 7.8})

这是行不通的:

a = dict(import='trade', 1=7.8)

这将导致以下错误:

    a = dict(import='trade', 1=7.8)
             ^
SyntaxError: invalid syntax

100

首先,使用花括号。否则,如果键值中包含奇怪字符(如=),就会遇到一致性问题。

# Works fine.
a = {
    'a': 'value',
    'b=c': 'value',
}

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)

25
这正是为什么有些人更喜欢使用dict()方法进行初始化的原因。这种方法可以强制字典的键必须是有效的标识符,这样它们就可以与**kwargs并存,并且这些键也可以作为有效的属性名称。 - RufusVS

65
第一个版本更好:
  • 它适用于所有类型的键,因此您可以例如说{1:'one',2:'two'}。第二个变体仅适用于(某些)字符串键。根据键的类型使用不同类型的语法将是不必要的不一致。
  • 它更快:

    $ python -m timeit "dict(a='value', another='value')"
    1000000 loops, best of 3: 0.79 usec per loop
    $ python -m timeit "{'a': 'value','another': 'value'}"
    1000000 loops, best of 3: 0.305 usec per loop
    
    如果字典字面值的特殊语法没有意图被使用,那么它可能不会存在。

7

我几乎总是使用花括号{}; 但在编写测试时,有些情况下我会使用关键字打包/解包,这种情况下dict()更易于维护,因为我不需要改变:

a=1,
b=2,

to:

'a': 1,
'b': 2,

它还在某些情况下有所帮助,例如我认为将来可能想将其转换为namedtuple或类实例。
在实现中,由于我的优化狂热,而且当我认为没有特别大的可维护性好处时,我总是更喜欢花括号。
在测试和实现中,如果存在以下任何一种可能,则永远不会使用dict():
- 键值不是字符串 - 键值不仅包含数字、ASCII字母和下划线 - 以整数开头(dict(1foo=2)会引发SyntaxError)

3

我认为第一种选项更好,因为你将访问值作为a ['a']或a ['another']。你的字典键是字符串,没有理由假装它们不是。对我来说,关键字语法刚开始看起来很聪明,但第二次看起来就很晦涩。只有当你使用 __dict__ 并且关键字稍后会变成属性时,这才对我有意义,之类的。


3

如果您需要向字典添加属性(附加到字典但不是键之一的内容),则需要使用第二种形式。 在这种情况下,您可以逐个初始化具有任意字符的键,例如:

    class mydict(dict): pass
    a = mydict()        
    a["b=c"] = 'value'
    a.test = False

3
有时候使用dict()是一个不错的选择:
a=dict(zip(['Mon','Tue','Wed','Thu','Fri'], [x for x in range(1, 6)]))

3
有一个枚举函数可以更好地完成这个任务。同样地,有一个 Enum 类型可以更好地完成你在这里所做的事情。此外,这并不是对问题的真正回答。 - dusktreader
{x:y for x,y in zip(['星期一','星期二','星期三','星期四','星期五'], [x for x in range(1, 6)])} - Vulwsztyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接