Python生成器-改变最后的结果



我试图在我的生成器的以下两个定义之间做出决定。哪个更好?哪个更"蟒化"?有没有办法减轻每一种方法的缺点?

def myGenerator1(howMany):
    result = [0,0,0]
    yield result
    for i in range(howMany)
        modifyListInPlace(result)
        yield result
for val in myGenerator1(1000):
    useValThenForgetIt(val)
def myGenerator2(howMany):
    result = (0,0,0)
    yield result
    for i in range(howMany)
        result = createNewUpdatedTuple(result)
        yield result
for val in myGenerator2(1000):
    useValThenForgetIt(val)

第一个修改了生成器返回的值,可能会干扰到我还没有预见到的调用代码。在这种情况下,第二个生成1000元组的垃圾,如果我增加"howMany"(我可能会这样做),则产生更多的垃圾。

作为一个例子,我给出的循环只是我当前对生成器的使用。我不认为我会保存它的值,但它是一个可能在其他地方有用的实用程序。

参考标准库,itertools模块中的组合函数都返回元组,即使底层算法是就地突变算法。例如,看看itertools.permutations.

的代码

这种设计(返回元组而不是列表)已被证明是健壮的。我担心,根据调用者对迭代器返回值的处理,变化列表方法会产生一些难以发现的bug。

另一个想法。对于未使用的结果,我不会太担心"创建数千个元组的垃圾"。Python的元组实现非常擅长重用以前处理过的元组(通过使用自由列表数组,它可以从以前使用过的元组创建一个新的元组,而无需调用内存分配器)。因此,元组版本的性能与列表版本一样,甚至更好。

第一个可以返回一个对象,然后在返回后不明显地修改它的事实对我来说是一个巨大的代码气味,无论你使用什么语言(即它不是"python"的问题)。另外,为什么要让一个函数一次又一次地为相同的值生成迭代器,并在每次生成之间进行修改呢?对我来说似乎很不直观。

如果你使用了这些值,那么myGenerator2创建的元组就不是垃圾。如果你一次只使用一个,它们永远不会同时存在,你的程序几乎肯定会做许多其他的内存分配/释放。与range(howMany)返回的列表不同,创建1,000个您从未实际使用过的整数(除非您使用Python3,在这种情况下range返回生成器而不是列表)。

如果有任何机会,调用者可能想要挂起对您的生成器返回的东西的引用(并且Python程序员通常期望,当给定生成器时,如果他们需要多次使用它们,则能够使用items = list(generator)),那么第二个要优越得多。

相关内容

  • 没有找到相关文章

最新更新