Python:在生成器中生成字典元素?

Posted

技术标签:

【中文标题】Python:在生成器中生成字典元素?【英文标题】:Python: Yield Dict Elements in generators? 【发布时间】:2011-10-06 19:04:20 【问题描述】:

在我说一句话之前,让我感谢社区是我最近的编程查询的权威位置。并假装这些赞美不是用语言表达的。无论如何,概率法则决定了我偶然发现了使用多功能搜索栏找不到的东西,所以我决定第一次明确要求。也许我只是没有使用足够 Pythonic 的术语进行搜索。或者我可能不喜欢谷歌搜索/***ing。无论如何...

我在玩 Python 协程和生成器。据我所知,你可以用生产者协程做任何生成器理解可以做的事情,尽管更冗长。我目前正在使用 Python 3,尽管关于 Python 2 的任何答案都不会错过。

所以我假设以下代码片段是等效的:

one_to_three = (num for num in range(1, 4))

...

def one_to_three():
    for num in range(1, 4):
        yield num

one_to_three_gen = one_to_three()

它适用于我的 Python 安装。如果我忽略该代码中的冗余示例,我会发现生成器理解很容易映射到生产者协程生成的生成器。作为 Pragmatic 博士,我尝试将相同的概念映射到 dicts,因为 dict 理解已经存在,我认为这两者是等价的:

one_to_three_doubles = num : num * 2 for num in range(1, 4)

...

def one_to_three_doubles():
    for num in range(1, 4):
        yield num : num * 2

one_to_three_doubles_gen = one_to_three_doubles()

第一个有效,但第二个无效。它在第 3 行的冒号上标记语法错误。

现在,要么我在语法上稍有失误,要么我对生产者协程的工作方式有很大的误解。我怀疑它失败的原因与您不能让协程返回列表而不是生成器相反,但我真的不知道。

所以,是的,修复该错误基本上就是我所要求的;提前致谢。我更喜欢一个能告诉我答案的答案,而不是给我一个全新的方法来实现结果,但显然如果这是唯一的方法......

【问题讨论】:

您说的是生成器,而不是协程。如果你想知道协程真的是阅读A Curious Course on Coroutines and Concurrency. 我认为同时存在生产者和消费者协程,并且使用 yielding 模式创建序列是协程创建生成器表达式的简单用法,因为执行暂停并在每个值的产生时恢复,它是如何跟踪它的位置的?不过可能是错的。 【参考方案1】:

字典推导确实像列表/集合推导和生成器表达式一样工作 - “主体”为 expr for vars in iterable 的 X 推导几乎等同于 X(expr for vars in iterable) - 而且您已经知道如何将生成器表达式转换为生成器.但请注意“相当多”位,因为直译不起作用(正如您所注意到的)并且根本没有必要(不会使实施变得更容易,实际上会很hacky)。

字典理解只有一点语法糖,看起来更像字典文字(冒号)。从语义上讲,它没有必要——它没有什么特别之处。停下来想一想:dict 理解必须在每次迭代中产生 两个 值,一个键和一个值。这正是冒号所代表的 - (key, value) 对(请记住,dict 接受 (key, value) 对的可迭代)。您不能在 dict 理解之外使用该语法糖,但您可以只对对使用元组。因此,等效的生成器将是:

def one_to_three_doubles():
    for num in range(1, 4):
        yield num, num * 2

【讨论】:

啊哈,这正是我想知道的;感谢您的及时回复。当你这样陈述它是有道理的,当你提到 dict 接受可迭代的对时,它“点击”了。 要创建字典,请使用dict(one_to_three_doubles()) 对@congusbongus 的进一步评论;你也可以写k: v for k, v in one_to_three_doubles()。当您想要更改结果字典的键或值而不更改生成函数时,这很有用。【参考方案2】:

我想从 python 函数中的 yield 生成一个 dict 并找到了这个问题。下面是返回字典的代码。

def _f():
    yield 'key1', 10
    yield 'key2', 20

def f(): return dict(_f())

print(f())
# Output:
'key1': 10, 'key2': 20

【讨论】:

以上是关于Python:在生成器中生成字典元素?的主要内容,如果未能解决你的问题,请参考以下文章

Python:在生成器对象上调用 list() 会产生不正确的结果

python中生成器

如何操作通过 itertuples 生成的命名元组专门删除一个元素并从剩余元素中生成一个字典?

Python生成器和迭代器

python 字典列表元组生成器的使用

python随机彩票号码生成器游戏