以下两个短语对我来说似乎是等价的。哪个更好?
data = [('a', 1), ('b', 1), ('b', 2)]
d1 = {}
d2 = {}
for key, val in data:
# variant 1)
d1[key] = d1.get(key, []) + [val]
# variant 2)
d2.setdefault(key, []).append(val)
结果是一样的,但是哪个版本更好或者更像是Python?
就我个人而言,我觉得版本2很难理解,因为对我来说setdefault很难理解。如果我理解正确,它会在字典中查找“key”的值,如果不可用,则在dict中输入“[%”,返回对该值或“[%”的引用,并在该引用后附加“val”。虽然它确实很平滑,但至少对我来说是不直观的。
在我看来,版本1更容易理解(如果可用,获取“key”的值,如果不可用,获取“[]),然后加入一个由[val]组成的列表并将结果放入“key”)。但是,虽然更直观的理解,我担心这个版本是不太好的表现,与所有这些名单创建。另一个缺点是“d1”在表达式中出现两次,这很容易出错。也许有一个更好的使用get的实现,但是现在我不知道了。
我的猜测是版本2,虽然对于缺乏经验的人来说更难掌握,但是速度更快,因此更可取。意见?
agf接受的答案并不是将like与like进行比较。之后:
d[0]
包含一个包含10000个项的列表,而在之后:d[0]
只是[]
。i、 e.d.setdefault
版本从不修改存储在d
中的列表。代码实际上应该是:而且事实上比错误的
setdefault
示例更快。这里的区别实际上是因为当您使用连接进行追加时,每次都会复制整个列表(并且一旦有10000个元素开始变得可测量)。使用
append
列表更新按O(1)摊销,即有效的恒定时间。最后,在最初的问题中还有两个未考虑的选项:
defaultdict
,或者只是测试字典,看看它是否已经包含了密钥。所以,假设
d3, d4 = defaultdict(list), {}
到目前为止,variant 1是最慢的,因为它每次都会复制列表,variant 2是第二慢的,variant 3是最快的,但如果您需要2.5以上的Python,它就不起作用,variant 4只是比variant 3慢一点。
如果可以的话,我会说使用variant 3,使用variant 4作为那些
defaultdict
不完全适合的地方的选项。避免两种原始变体。您可能需要查看
collections
模块中的defaultdict
。以下内容与您的示例相同。还有更多的here。
你的两个例子做了同样的事情,但这并不意味着
get
和setdefault
做了。两者之间的区别基本上是每次都手动设置
d[key]
指向列表,而setdefault
只在列表未设置时才自动设置d[key]
指向列表。使这两种方法尽可能相似,我运行
得到了
因此
setdefault
比get
快10%。通过
get
方法,您可以比使用setdefault
做的更少。即使不想设置密钥,也可以使用它来避免在密钥不存在时(如果这是经常发生的情况)获得KeyError
。有关这两种方法的更多信息,请参见Use cases for the 'setdefault' dict method和dict.get() method returns a pointer。
关于
setdefault
的线程得出结论,大多数情况下,您希望使用defaultdict
。关于get
的线程得出结论,它速度很慢,而且通常您最好(从速度上看)执行双重查找、使用defaultdict或处理错误(取决于字典的大小和您的用例)。相关问题 更多 >
编程相关推荐