是否可以在python中进行平坦的懒惰生成?例如,我在下面的代码中尝试做的是传递os.walk的结果并尝试仅返回那些结果
def os_walk_transcript(self, walk_results):
"""Takes the results of os.walk on the data directory and returns a list of absolute paths"""
file_check = lambda walk: len(walk[2]) > 0
srt_prelim = lambda walk: ".srt.sjson" in " ".join(walk[2])
relevant_results = (entry for entry in walk_results if file_check(entry) and srt_prelim(entry))
return (self.os_path_tuple_srts(result) for result in relevant_results)
def os_path_tuple_srts(self, os_walk_tuple):
srt_check = lambda file_name: file_name[-10:] == ".srt.sjson"
directory, subfolders, file_paths = os_walk_tuple
return [os.path.join(directory, file_path) for file_path in file_paths if srt_check(file_path)]
重要的是os_walk_transcript的结果被懒惰地评估,但我希望能够以平面的方式评估它,而不是它当前的嵌套列表评估。
例如:目前,当我从生成的生成器中请求结果时,我会得到["1.srt.sjson", "2.srt.sjson", "3.srt.sjson"]
的完整列表,如果我再次调用它,我会得到:["4.srt.sjson"]
我正在工作数据足够大且不一致的项目,这种行为会导致性能不一致,偶尔会导致速度比我想要的速度慢。有没有办法强迫懒惰的评估更加懒惰,只需一次加载一个对象?
答案 0 :(得分:1)
您可以使用itertools chain.from_iterable()。文档为here.
基本上,您可以像这样使用它:
import itertools
myList = [[1,2,3],[4,5],[6],[7,8,9]]
itr = itertools.chain.from_iterator(myList)
itr现在将成为一个生成器对象,每次调用它时都会返回下一个元素。 (在这种情况下,它将完全像xrange(10)
)
答案 1 :(得分:-1)
难道你不能只做这样的功能吗?
def lazyarray(index):
return str(index) + ".srt.sjson"
然后你甚至可以做到这一点
firstTen = [lazyarray(x) for x in xrange(10)]
完全懒惰,实现起来非常简单。如果你想减少懒惰(缓存计算),你可能会这样做。
cache = []
def lazyarray(index):
if len(cache) <= index:
cache += ["" for x in xrange(index - len(cache))]
if cache[index] == "":
cache[index] = str(index) + ".srt.sjson"
return cache[index]
我还没有测试过任何这样的代码,所以可能需要调整,而且我不处理文件,但这不是你要问的问题吗?
无论你在哪里使用代码,而不是说
lazyarray[5]
只是说
lazyarray(5)
它将与数组具有相同的效果。
编辑:
您甚至可以覆盖__getitem__
方法,如here所示,并且只根据我在上面发布的代码提供自定义生成器类。