我在What is the most "pythonic" way to iterate over a list in chunks?研究了Nosklo的回应,他在那里定义了函数:
def chunker(seq, size):
return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
有人可以解释一下,当循环后面的返回是如何工作的吗? 我试着做以下事情:
def chunker2(seq, size):
for pos in xrange(0, len(seq), size):
return seq[pos:pos + size]
但我没有得到相同的结果。
注意,在Nosklo示例中,chunker()
被迭代调用,如下例所示:
animals = ['cat', 'dog', 'rabbit', 'duck', 'bird', 'cow', 'gnu', 'fish']
for group in chunker(animals, 3):
print group
通过添加打印件,我注意到后一个for
循环执行了3次(它与animals
列表相同),但chunker
函数中的for循环只执行一次。那么,为什么只有一个回归,我可以看到3个印刷品?
答案 0 :(得分:3)
nosklo chunker
函数的返回值称为生成器,它是在迭代时生成值的对象。在这种情况下,生成器是使用generator expression创建的,generator function是括号中不可分割的代码:(seq[pos:pos + size] for pos in xrange(0, len(seq), size))
。
>>> def chunker(seq, size):
... return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
...
>>> result = chunker([1, 2, 3], 2)
>>> print(result)
<generator object <genexpr> at 0x10581e1e0>
>>> next(result)
[1, 2]
>>> next(result)
[3]
关于被调用的内容,我们可以像这样重写循环代码以更好地看到它:
>>> generator = chunker(animals, 3)
>>> for chunk in generator:
... print chunk
...
['cat', 'dog', 'rabbit']
['duck', 'bird', 'cow']
['gnu', 'fish']
chunker
函数只被调用一次并返回生成器对象,我们将其存储在generator
变量中。 for
循环只适用于此generator
对象,并将其调用3次。
为了能够打印此生成器的实际调用,您必须在生成器表达式print
中包含(seq[pos:pos + size] for pos in xrange(0, len(seq), size))
语句,这是不允许的。但是我们可以使用yield
语句将此生成器表达式重写为普通{{3}},这是一种更详细但也更通用的生成器形式,我们可以在其中包含print
语句,它将作为你最初的期望:
>>> def chunker2(seq, size):
... for pos in xrange(0, len(seq), size):
... print('chunker2 generator called')
... yield seq[pos:pos + size]
...
>>> for group in chunker2(animals, 3):
... print group
...
chunker2 generator called
['cat', 'dog', 'rabbit']
chunker2 generator called
['duck', 'bird', 'cow']
chunker2 generator called
['gnu', 'fish']
这里chunker2
函数本身就是实际的生成器,并被调用3次。