我想结合这些:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
进入单个字典:
{'name': 'Monty', 'age': 42, 'food': 'spam'}
原文由 Guido 发布,翻译遵循 CC BY-SA 4.0 许可协议
我想结合这些:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
进入单个字典:
{'name': 'Monty', 'age': 42, 'food': 'spam'}
原文由 Guido 发布,翻译遵循 CC BY-SA 4.0 许可协议
想象一下,你有:
> keys = ('name', 'age', 'food') > values = ('Monty', 42, 'spam') > > ``` > > **生成以下字典的最简单方法是什么?** > > ``` > dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'} > > ``` ## 最高性能, `dict` 构造函数 `zip`
new_dict = dict(zip(keys, values))
在 Python 3 中,zip 现在返回一个惰性迭代器,这是目前性能最高的方法。
`dict(zip(keys, values))` 确实需要对 `dict` 和 `zip` 进行一次性全局查找,但它不处理任何形式的不必要的中间数据结构函数应用程序中的本地查找。
## 亚军,听写理解:
使用 dict 构造函数的一个接近的亚军是使用 dict 理解的本机语法(不是 _列表_ 理解,正如其他人错误地指出的那样):
new_dict = {k: v for k, v in zip(keys, values)}
当您需要根据键或值进行映射或过滤时选择此选项。
在 Python 2 中, `zip` 返回一个列表,为避免创建不必要的列表,请使用 `izip` 代替(别名为 zip 可以减少迁移到 Python 3 时的代码更改)。
from itertools import izip as zip
所以那仍然是(2.7):
new_dict = {k: v for k, v in zip(keys, values)}
## Python 2,适用于 <= 2.6
`izip` from `itertools` becomes `zip` in Python 3. `izip` is better than zip for Python 2 (because it avoids the unnecessary list creation) ,并且适用于 2.6 或以下版本:
from itertools import izip new_dict = dict(izip(keys, values))
## 所有情况的结果:
在所有情况下:
new_dict {‘age’: 42, ‘name’: ‘Monty’, ‘food’: ‘spam’}
## 解释:
如果我们查看 `dict` 上的帮助,我们会发现它采用多种形式的参数:
help(dict)
class dict(object) | dict() -> new empty dictionary | dict(mapping) -> new dictionary initialized from a mapping object’s | (key, value) pairs | dict(iterable) -> new dictionary initialized as if via: | d = {} | for k, v in iterable: | d[k] = v | dict(**kwargs) -> new dictionary initialized with the name=value pairs | in the keyword argument list. For example: dict(one=1, two=2)
最佳方法是使用可迭代对象,同时避免创建不必要的数据结构。在 Python 2 中, zip 创建了一个不必要的列表:
zip(keys, values) [(‘name’, ‘Monty’), (‘age’, 42), (‘food’, ‘spam’)]
在 Python 3 中,等价物是:
list(zip(keys, values)) [(‘name’, ‘Monty’), (‘age’, 42), (‘food’, ‘spam’)]
而 Python 3 的 `zip` 仅仅创建了一个可迭代对象:
zip(keys, values)
由于我们希望避免创建不必要的数据结构,因此我们通常希望避免使用 Python 2 的 `zip` (因为它会创建不必要的列表)。
## 性能较差的替代品:
这是传递给 dict 构造函数的生成器表达式:
generator_expression = ((k, v) for k, v in zip(keys, values)) dict(generator_expression)
或等效地:
dict((k, v) for k, v in zip(keys, values))
这是传递给 dict 构造函数的列表理解:
dict([(k, v) for k, v in zip(keys, values)])
在前两种情况下,一个额外的非操作(因此不必要的)计算层被放置在 zip 可迭代对象上,而在列表理解的情况下,不必要地创建了一个额外的列表。我希望它们的性能都较低,当然不会更高。
## 绩效考核:
在 Nix 提供的 64 位 Python 3.8.2 中,在 Ubuntu 16.04 上,从最快到最慢排序:
min(timeit.repeat(lambda: dict(zip(keys, values)))) 0.6695233230129816 min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)})) 0.6941362579818815 min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))})) 0.8782548159942962
min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)]))) 1.077607496001292 min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values)))) 1.1840861019445583
`dict(zip(keys, values))` 即使使用小的键和值集也能胜出,但对于更大的集合,性能差异会变得更大。
一位评论者说:
> `min` 似乎是一种比较性能的糟糕方法。当然 `mean` 和/或 `max` 对于实际使用来说是更有用的指标。
我们使用 `min` 因为这些算法是确定性的。我们想知道算法在可能的最佳条件下的性能。
如果操作系统由于任何原因挂起,它与我们要比较的内容无关,因此我们需要从我们的分析中排除这些类型的结果。
如果我们使用 `mean` ,这些事件会极大地扭曲我们的结果,如果我们使用 `max` 我们只会得到最极端的结果 \- 最有可能受此类事件影响的结果.
评论者还说:
> 在 python 3.6.8 中,使用平均值,dict 理解确实更快,对于这些小列表,速度提高了大约 30%。对于更大的列表(10k 随机数), `dict` 调用速度大约快 10%。
我想我们的意思是 `dict(zip(...` 有 10k 个随机数。这听起来像是一个相当不寻常的用例。最直接的调用在大型数据集中占主导地位确实是有道理的,考虑到运行该测试需要多长时间,如果操作系统挂起占主导地位,我也不会感到惊讶,这会进一步扭曲您的数字。如果您使用 `mean` 或 `max` 我会认为您的结果毫无意义。
让我们在我们的顶级示例中使用更实际的尺寸:
import numpy import timeit l1 = list(numpy.random.random(100)) l2 = list(numpy.random.random(100))
我们在这里看到 `dict(zip(...` 对于更大的数据集确实运行速度快了大约 20%。
min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)})) 9.698965263989521 min(timeit.repeat(lambda: dict(zip(l1, l2)))) 7.9965161079890095
”`
原文由 Russia Must Remove Putin 发布,翻译遵循 CC BY-SA 4.0 许可协议
4 回答4.4k 阅读✓ 已解决
4 回答3.8k 阅读✓ 已解决
1 回答3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
1 回答4.5k 阅读✓ 已解决
1 回答3.8k 阅读✓ 已解决
1 回答2.8k 阅读✓ 已解决
像这样:
瞧 :-) 成对的
dict
构造函数和zip
函数非常有用。