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

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

我在玩 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 模式创建序列是协程创建生成器表达式的简单用法,因为执行暂停并在每个值的产生时恢复,它是如何跟踪它的位置的?不过可能是错的。

标签: python dictionary generator list-comprehension


【解决方案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}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-30
    • 2020-01-18
    • 2013-03-20
    • 1970-01-01
    • 2022-01-17
    • 2017-05-27
    • 2014-10-04
    • 2016-05-07
    相关资源
    最近更新 更多