0

是否可以在 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"]我正在一个项目中工作,其中数据足够大并且足够不一致,以至于这种行为导致性能不一致,有时这会导致事情比我想要的慢。有什么办法可以让惰性求值变得更惰性,一次只加载一个对象?

4

2 回答 2

1

您可以使用 itertools chain.from_iterable()。文档在这里。

基本上,您可以像这样使用它:

import itertools

myList = [[1,2,3],[4,5],[6],[7,8,9]]

itr = itertools.chain.from_iterator(myList)

it 现在将是一个生成器对象,每次调用它时都会返回下一个元素。(在这种情况下,它会完全像xrange(10)

于 2013-06-12T22:25:35.303 回答
-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__方法,如此处所示并且仅具有基于我上面发布的代码的自定义生成器类。

于 2013-06-12T22:01:41.143 回答