[]和{}与list()和dict(),哪个更好?


Answers:


197

在速度方面,空列表/字典没有竞争:

>>> from timeit import timeit
>>> timeit("[]")
0.040084982867934334
>>> timeit("list()")
0.17704233359267718
>>> timeit("{}")
0.033620194745424214
>>> timeit("dict()")
0.1821558326547077

对于非空:

>>> timeit("[1,2,3]")
0.24316302770330367
>>> timeit("list((1,2,3))")
0.44744206316727286
>>> timeit("list(foo)", setup="foo=(1,2,3)")
0.446036018543964
>>> timeit("{'a':1, 'b':2, 'c':3}")
0.20868602015059423
>>> timeit("dict(a=1, b=2, c=3)")
0.47635635255323905
>>> timeit("dict(bar)", setup="bar=[('a', 1), ('b', 2), ('c', 3)]")
0.9028228448029267

另外,使用方括号表示法还可以使您使用列表和字典理解,这可能就足够了。


4
字典和列表的理解也可以使用英文名称来完成。示例:list(i for i in range(10) if i % 2)
Zags 2014年

4
为什么{}和[]这么快有原因吗?我以为它们只是别名。
贾斯汀D.15年

timeit似乎不能给出准确的时间。根据基准测试,它似乎需要200毫秒左右的时间,比正常的http调用要慢得多。尝试在外壳中正常运行dict(),然后运行timeit(“ dict()”),您会发现执行时有明显的区别。
piyush

2
@piyush实际上,该timeit()函数报告执行指定数量的迭代的总时间1000000,默认情况下是这样。因此,上面的示例是运行一百万次代码段的秒数。例如timeit('dict()', number=1) // -> 4.0531158447265625e-06(一次迭代)而timeit('dict()') // -> 0.12412905693054199(一百万次迭代)
Greg Haskins

@GregHaskins,因此在那种情况下,我不认为应该担心使用dict()或{},除非循环遍历一百万条记录并在循环中使用dict()。
piyush

37

我认为[]并且{}是创建空列表/字典的最Python易懂的方法。

不过请注意set(),例如:

this_set = {5}
some_other_set = {}

可能会造成混乱。第一个创建一个带有一个元素的集合,第二个创建一个空字典而不是一个集合。


4
{}总是创建一个空的字典。{1,2,3}在2.7+ 2.6版本中创建了一个集合,但在旧版本中是语法错误。
ThiefMaster 2011年

1
抱歉?那是一个变量,其名称some_epic_set指向一个空dict对象……这不是一个空集。对于空集,您需要使用set()
6502

2
@ 6502:的确如此,但这是一个常见的陷阱,它{5}创建了一个包含一个元素的集合,5并且{}是空洞的字典。
orlp 2011年

1
哇,真令人困惑。尽管如此,这也不是混淆的不良设计水平。:-)
Falken教授2012年

4
@EnderLook:实际上,通过广义拆包,您可以使用文字语法{*()}将其设为空set。我称其为单眼猴操作员。:-)
ShadowRanger

17

该字典的文字可能是一个小小的其字节码更短更快一点:

In [1]: import dis
In [2]: a = lambda: {}
In [3]: b = lambda: dict()

In [4]: dis.dis(a)
  1           0 BUILD_MAP                0
              3 RETURN_VALUE

In [5]: dis.dis(b)
  1           0 LOAD_GLOBAL              0 (dict)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

同样适用于listVS[]


8
假设BUILD_MAP和LOAD_GLOBAL是恒定时间,并且花费相同的时间。不大可能。timeit给出了更好的估计。
Jamie Pate 2014年

更可能的CALL_FUNCTION,至少要花费与BUILD_MAP(本质上称为的函数是BUILD_MAP)一样多的时间,而LOAD_GLOBAL这仅仅是额外的开销。
chepner '19


3

对于[]和list()之间的差异,存在一个陷阱,我没有看到其他人指出过。如果将字典用作列表的成员,则两者将给出完全不同的结果:

In [1]: foo_dict = {"1":"foo", "2":"bar"}

In [2]: [foo_dict]
Out [2]: [{'1': 'foo', '2': 'bar'}]

In [3]: list(foo_dict)
Out [3]: ['1', '2'] 

[foo_dict]使用可获得相同的结果list((foo_dict,))。该list()方法采用一个iterable作为唯一参数,并对其进行迭代以将元素添加到列表中。这样做会导致类似的陷阱,list(some_list)从而使列表变平。
sotrh

1

list()和[]的工作方式不同:

>>> def a(p=None):
...     print(id(p))
... 
>>> for r in range(3):
...     a([])
... 
139969725291904
139969725291904
139969725291904
>>> for r in range(3):
...     a(list())
... 
139969725367296
139969725367552
139969725367616

list()总是在堆中创建新对象,但是[]可以出于多种原因重用存储单元。


0

如下所示,[]和list()在行为上有一个区别。如果要返回数字列表,则需要使用list(),否则我们将获得一个map对象!不确定如何解释。

sth = [(1,2), (3,4),(5,6)]
sth2 = map(lambda x: x[1], sth) 
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>

sth2 = [map(lambda x: x[1], sth)]
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>
type(sth2) # list 
type(sth2[0]) # map

sth2 = list(map(lambda x: x[1], sth))
print(sth2) #[2, 4, 6]
type(sth2) # list
type(sth2[0]) # int

这似乎是使用range()函数示例的行为解释>>> print(range(10))#range(0,10)range()的行为类似于列表,但它不是列表。它是一个对象,当您在序列上进行迭代时,它会返回序列中的后续项,它实际上并不构成列表,从而节省了空间。这样的对象是可迭代的,也就是说,适合作为功能和构造的目标,这些功能和构造期望它们可以从中获取连续的物品,直到用完为止。函数list()从可迭代对象创建列表:>>>​​ list(range(5))#[0,1,2,3,4]
sebtac

1
结果是[]存储了可迭代对象;list()从相同的可迭代对象创建列表
sebtac

0

方括号对表示列表对象或索引下标my_List [x]中的一个。

大括号对表示字典对象。

a_list = ['on','off',1,2]

a_dict = {开启:1,关闭:2}


-5

大多数时候,这主要是选择问题。这是一个偏好问题。

但是请注意,例如,如果您有数字键,则不能这样做:

mydict = dict(1="foo", 2="bar")

你所要做的:

mydict = {"1":"foo", "2":"bar"}

7
这是错误的...您需要做mydict = {1:"foo", 2:"bar"}(不带引号)。
6502

8
这不仅仅是“错误”。键是字符串/整数,具体取决于您是否引用它们。
ThiefMaster 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.