今天是发电机。我今天看到一个question想要找到一种方法来递归地压缩列表而不使用循环和导入。 tobias_k使用以下代码回答:
def flatten(test_list):
if isinstance(test_list, list):
if len(test_list) == 0:
return []
first, rest = test_list[0], test_list[1:]
return flatten(first) + flatten(rest)
else:
return [test_list]
有没有办法创建一个生成器(保持规则:没有导入,循环)?
注意:它纯粹是教育性的。我知道这不是最好的主意,但不知道该怎么做。
答案 0 :(得分:4)
在Python 3.3(开发版)中,您可以使用yield from
构造来避免显式循环:
def flatten(x):
if isinstance(x, list):
if x:
first, rest = x[0], x[1:]
yield from flatten(first)
yield from flatten(rest)
else:
yield x
在当前版本中,我无法想到不使用itertools.chain
的解决方案。
答案 1 :(得分:4)
generator function是一个包含至少一个yield
statement和没有return
语句的函数。当调用生成器函数时,它返回一个生成器迭代器,当迭代时(例如通过for
循环,或显式地使用next
)运行函数体,冻结其状态并将控制返回到每个yield
语句(以及Python 3.3,yield from
语句中的调用者。)
Python函数内部的流控制总是向前发展;没有像设置当前帧{1}那样的黑客(正如(愚人节)goto
statement所做的那样),控制达到早期点的唯一方法是使用循环(f_lineno
或for
)。因此,如果没有循环或while
,可以调用生成器迭代器的最大次数受生成器函数中yield from
语句数量的限制。
请注意,编写返回迭代器的yield
很容易;采用原始解决方案并编写flatten
即可。但那不是生成器迭代器,函数也不是生成器函数。
这是一个滥用return iter(flatten(first) + flatten(rest))
来实现无循环迭代的实现。不幸的是,它必须使用f_lineno
:
import sys
答案 2 :(得分:-1)
完成单行列表理解:
def flatten (test_list):
return [element for temp in test_list for element in flatten(temp)] if isinstance(test_list, list) else [test_list]
print(flatten([1, [2, 1, [3, 6, 7]], [1, 2, [3, 2, 3], 4, [1, 2, 3, 4, 5]]]))
#[1, 2, 1, 3, 6, 7, 1, 2, 3, 2, 3, 4, 1, 2, 3, 4, 5]