理解(list、set、dict 和生成器表达式)都按照处理单个项目的原则工作。产生两个键值对的函数不是单个项目,因此您需要将结果拆分为单个项目。理解不支持PEP 448 unpacking syntax,只适用于非理解形式。
您必须在返回的字典的 dict.items() 上添加一个额外的循环:
{k: v for i in range(5) for k, v in mkdict(i).items()}
您也可以使用 dict() 类型,因为它接受可迭代的键值对:
dict(item for i in range(5) for item in mkdict(i).items())
你也可以使用itertools.chain.from_iterable():
from itertools import chain
dict(chain.from_iterable(mkdict(i).items() for i in range(5)))
如果mkdict() 是用编译语言实现的(来自库或用 Cython 等实现)并且迭代次数足够大,则可能值得降低可读性并使用map() function 申请范围值的mkdict() 函数和生成的每个字典的未绑定dict.items 方法:
dict(chain.from_iterable(map(dict.items, map(mkdict, range(5)))))
在这里,这并没有太大的可能性,因为mkdict() 是在 Python 中实现的,因此map() 必须回调 Python 解释器来获取字典。但是对于不这样做的函数,上面的表达式完全在本机机器代码中执行迭代和字典处理,完全避免了 Python 解释器循环。
每个选项的演示:
>>> def mkdict(i):
... # Simplified example
... return {i: i, 2*i: 2*i}
...
>>> {k: v for i in range(5) for k, v in mkdict(i).items()}
{0: 0, 1: 1, 2: 2, 4: 4, 3: 3, 6: 6, 8: 8}
>>> dict(item for i in range(5) for item in mkdict(i).items())
{0: 0, 1: 1, 2: 2, 4: 4, 3: 3, 6: 6, 8: 8}
>>> from itertools import chain
>>> dict(chain.from_iterable(mkdict(i).items() for i in range(5)))
{0: 0, 1: 1, 2: 2, 4: 4, 3: 3, 6: 6, 8: 8}
>>> dict(chain.from_iterable(map(dict.items, map(mkdict, range(5)))))
{0: 0, 1: 1, 2: 2, 4: 4, 3: 3, 6: 6, 8: 8}
请注意,PEP 448 明确排除了推导式,但未来的 Python 版本可以为该语言添加类似的内容。引用自PEP abstract section:
此 PEP 不包括列表、集合和字典推导中的解包运算符,尽管未来的提议并未排除这一点。