【问题标题】:How to Pythonically yield all values from a list?如何以 Python 方式从列表中生成所有值?
【发布时间】:2011-01-30 16:49:47
【问题描述】:

假设我有一个不希望返回但希望从中产生值的列表。最pythonic的方法是什么?

这就是我的意思。由于一些非惰性计算,我计算了列表['a', 'b', 'c', 'd'],但是我在项目中的代码使用了惰性计算,所以我想从我的函数中产生值而不是返回整个列表。

我目前是这样写的:

my_list = ['a', 'b', 'c', 'd']
for item in my_list:
    yield item

但这对我来说并不像pythonic。

【问题讨论】:

  • 为什么需要这样做,您可以使用“for x in container”,其中容器是列表或容器是迭代器......无论类型如何,语法都不会改变,所以为什么它是列表还是迭代器很重要?您仍然必须坚持列表才能从中获得收益,因此只需传递列表即可。
  • 旁注:加上“List”,由于前导大写,很多人会认为它是一个类名(参见 PEP 8)。您可以使用“list_”或“my_list”等。
  • EOL,感谢您的评论。谢谢。
  • 一个可迭代对象可以被认为是它自己的生成器。也就是说,如果我能写出for i in my_iterable:,它会像发电机一样行走,像发电机一样嘎嘎作响。

标签: python generator yield


【解决方案1】:

完成这项任务的最佳 Python 方式是

In [1]: my_list = ['a', 'b', 'c', 'd']

In [2]: (x for x in my_list)
Out[2]: <generator object <genexpr> at 0x7fd9e4fdc230>

【讨论】:

  • 对于这个答案的反对者,我可以问为什么这是一个坏主意吗?这个答案似乎是最容易做的事情。
【解决方案2】:

由于这个问题没有具体说明;我将提供适用于Python >= 3.3的答案

如果您只需要返回该列表,请按照Anurag suggests 执行操作,但如果出于某种原因,所讨论的函数确实需要成为生成器,您可以委托给另一个生成器;假设您想为结果列表添加后缀,但前提是列表首先用完。

def foo():
    list_ = ['a', 'b', 'c', 'd']
    yield from list_

    if something:
        yield this
        yield that
        yield something_else

但是,在 3.3 之前的 python 版本中,您不能使用这种语法;您必须使用问题中的代码,在正文中使用 for 循环和单个 yield 语句。

或者;您可以将生成器包装在常规函数中并返回 chained 结果:这也具有在 python 2 和 3 中工作的优势

from itertools import chain

def foo():
    list_ = ['a', 'b', 'c', 'd']

    def _foo_suffix():
        if something:
            yield this
            yield that
            yield something_else

    return chain(list_, _foo_suffix())

【讨论】:

  • yield from list_ 功能是一个很好的语法,也是我来这里寻找的。可惜我不能在 2.7 中使用它。
【解决方案3】:

使用iter 创建一个列表迭代器,例如

return iter(List)

如果你已经有一个列表,你可以直接返回它,这样会更有效率。

【讨论】:

  • 好问题。我没有答案。我将返回整个列表。我只是认为返回一个生成器是一个好主意,因为项目中的所有内容都使用了生成器(除了这个地方 - 我从一个不懒惰的库中得到这个列表)。
  • 这太过分了,因为对 iter 的调用完全是多余的。
  • iter 是一种矫枉过正,但并非完全多余,它可用于在遍历列表时记住您在哪里,您可以将其传递,使用列表您必须传递一个索引也是
  • @Anurag - 这似乎没有回答这个问题:如果我不想在那个时候返回怎么办,我想从列表中产生所有东西然后继续(可能产生更多的东西) ?这很常见(例如,在遍历递归结构时),并且像 bodacydo 一样,我不认为“for x in list yield x”解决方案是 Pythonic。
  • @Edmund 的答案是针对 OP 提出的问题,他已接受它作为答案。你的建议不是他的需要,也许你可以问一个单独的问题。
【解决方案4】:

你可以通过说来构建一个生成器

(x for x in List)

【讨论】:

  • 所以我可以return (x for x in list)?
  • 是的。但我认为这不会为您节省太多精力,因为您已经计算了整个列表,为什么不返回它呢?
  • 内置的 iter() 为您完成了这项工作:不需要生成器表达式,这也有速度较慢的缺点。
猜你喜欢
  • 2016-12-07
  • 1970-01-01
  • 2017-02-12
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多