【问题标题】:Different speed of generator to list conversion生成器到列表转换的不同速度
【发布时间】:2018-02-14 13:01:56
【问题描述】:

问题

所以我编写了一个 python 函数,它通过递归生成嵌套列表的所有元素来展平列表。我想出了 2 个不同版本的生成器创建函数(不是 100% 相同)。

这里有两个版本:

def iterflatten_v1(lst):
    for x in lst:
        if isinstance(x, (list, tuple)):
            yield from iterflatten_v1(x)
        else:
            yield x

def flatten_v1(lst):
    return list(iterflatten_v1(lst))

def iterflatten_v2(lst):
    for x in lst:
        try:
            yield from iterflatten_v2(x)
        except TypeError:
            yield x

def flatten_v2(lst):
    return list(iterflatten_v2(lst))

然后我使用以下代码测试了这两个函数的速度(timing function):

import time

def timing(f, a, n):
    print(f.__name__)
    r = range(n)
    t1 = time.clock()
    for i in r:
        f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a)
    t2 = time.clock()
    print(round(t2-t1, 3))

nested = [1, 1, 1, [1, 1, [1, 1, 1, [1, 1, 1, 1, [1, 1, 1, 1], 1, 1], 1, 1], 1], 1]
data = [nested for i in range(1000)]

timing(iterflatten_v1, data, 1000)  # 0.003
timing(iterflatten_v2, data, 1000)  # 0.003
timing(flatten_v1, data, 10)  # 1.647
timing(flatten_v2, data, 10)  # 3.005

问题

为什么iterflatten_v1 生成器的转换速度几乎是iterflatten_v2 生成器的两倍,即使生成器函数具有相同的速度?

【问题讨论】:

  • 因为您在 v2 中处理了更多异常(每个叶值一个异常),所有这些都增加了开销。
  • v2 还将字符串转换为字符列表,这可能是相当意外的行为。
  • @deceze 但是 v2 的开销不会显示在它的时间上吗?还是在我遍历它们时计算生成器?
  • 这让我想起了典型的“宽恕与许可”的困境。为此,你可能会觉得this post 很有趣
  • 嗯,是的,除非你迭代它,否则生成器不会做任何事情。

标签: python list generator


【解决方案1】:

正如 cmets 中所说,在这种情况下,异常处理比测试类型实例消耗更多的内存。

但是您对两者的计时都是正确的,并且计时可能会因数据而异(如果数据仅包含整数,您会更频繁地遇到异常,并且与 v1 相比,v2 会更慢)

请注意,如果您没有 tuplelist 的子代,您可以通过 not 使用 isinstance(检查基类)获得 50% 的加速,并检查确切的类型:

def iterflatten_v1(lst):
    for x in lst:
        if type(x) in (list, tuple):
            yield from iterflatten_v1(x)
        else:
            yield x

在我的机器上,isinstance 版本我得到 1.5 秒,而这个版本不到 1 秒。

(是的,我测试了 isinstance(x,collections.Sequence) 并且非常失望,因为它甚至比测试 2 种类型还要慢)

【讨论】:

    猜你喜欢
    • 2011-04-23
    • 2021-12-08
    • 2018-09-14
    • 2013-09-10
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多