gpt4 book ai didi

python - 为什么我不想立即将所有可迭代对象转换为具有定义长度的内容(例如列表)?

转载 作者:行者123 更新时间:2023-12-03 22:28:46 25 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

7 个月前关闭。




Improve this question




我不确定为什么我不会总是转换为列表。为什么我不想立即将所有可迭代对象转换为具有定义长度的内容(例如列表)?

最佳答案

欢迎来到社区!

  • “将可迭代对象转换为列表”通常是 O(N)/线性运算
  • “处理列表中的所有元素”通常是 O(N)/线性运算

  • 在对其进行处理之前,通常不应将可迭代对象转换为列表的原因是因为它会执行 2 * N为应该只需要的东西工作 N操作。
    (正如一些用户在评论中提到的那样,这里有一些关于 Big-O 复杂性的严重滥用符号。对于时间复杂度界限,我们忽略常量,而是关注与极限中的类似算法相比的行为。 这里 我们将专注于一个特定案例,并对其中一些在实践中的表现进行基准测试。)

    以下是我们感兴趣的两个案例:
    def compute_over_iterable():
    """Initialize `values` as an iterable, and do computation over it."""
    values = range(10000)
    result = []
    for entry in values:
    result.append(entry + 1)
    return result
    def compute_over_iterable_to_list():
    """Initialize `values` as an iterable, cast to a list, then compute:"""
    values = list(range(10000))
    result = []
    for entry in values:
    result.append(entry + 1)
    return result
    pytest-benchmark ,我们可以看到这些案例的表现:
    ----------------------------------- benchmark: 2 tests -----------------------------------
    Name (time in us) Min Max Mean
    ------------------------------------------------------------------------------------------
    test_iterable 781.3790 (1.0) 1,118.6880 (1.0) 837.1683 (1.0)
    test_iterable_to_list 1,000.4090 (1.28) 1,524.6950 (1.36) 1,138.6464 (1.36)
    ------------------------------------------------------------------------------------------
    在这种情况下,我们看到情况 (2),其中我们将可迭代对象转换为列表所花费的时间比直接使用可迭代对象长约 1.36 倍。
    list(range(10000)) 以来,这两个结果都相当接近cast 在 Python 的底层 C 实现中处理。如果您完全在 Python 中执行此操作,则差异会更加明显:
    def compute_over_iterable_list_comprehension():
    values = range(10000)
    values_cast = [i for i in values]
    result = []
    for entry in values_cast:
    result.append(entry + 1)
    return result
    我们看到它花费的时间是直接使用可迭代对象的大约 1.5 倍:
    ------------------------------------------ benchmark: 3 tests ------------------------------------------
    Name (time in us) Min Max Mean
    --------------------------------------------------------------------------------------------------------
    test_iterable 844.9320 (1.0) 1,014.3210 (1.0) 896.8944 (1.0)
    test_iterable_to_list 1,079.2420 (1.28) 1,370.0570 (1.35) 1,140.3908 (1.27)
    test_iterable_to_list_comprehension 1,269.8290 (1.50) 1,662.9790 (1.64) 1,336.5758 (1.49)
    --------------------------------------------------------------------------------------------------------

    一些异常(exception)和有趣的案例 MemoryView'@user2357112 支持莫妮卡' shared an interesting case in the comments我不熟悉的。它涉及 MemoryViews :

    "This usually requires an object with a means of converting it to a list other than just calling list on it. It still wastes memory and usually doesn't save much time, so it's usually not worth bothering."


    出于好奇,我将这些添加到单独的基准测试中。以下是重点介绍三种情况的基本概述:
    def compute_over_memory_view():
    values = memoryview(b'x' * 10000)
    # ...

    def compute_over_memory_view_tolist():
    values = memoryview(b'x' * 10000)
    for entry in values.tolist():
    # ...

    def compute_over_memory_view_cast():
    values = memoryview(b'x' * 10000)
    values_cast = list(values)
    # ...
    我的基准测试似乎表明调用 tolist memoryview 对象上的方法与直接在 memoryview 上操作几乎没有区别,但相比之下,转换为列表( list(values) )要慢得多。
    -------------------------- benchmark 'Memory Views': 3 tests ---------------------------
    Name (time in us) Min Mean Max
    ----------------------------------------------------------------------------------------
    test_memory_view 711.5030 (1.0) 774.2104 (1.0) 990.5890 (1.0)
    test_memory_view_tolist 745.4060 (1.05) 822.1782 (1.06) 1,154.2550 (1.17)
    test_memory_view_cast 860.5850 (1.21) 995.6708 (1.29) 1,290.4440 (1.30)
    ----------------------------------------------------------------------------------------
    无限长度的可迭代对象
    '@Tomerikoo' 提出了另一个好观点:可迭代对象可以是无限的。在这种情况下,尝试将可迭代对象转换为有限长度的对象可能会使您陷入无限循环。
    这是一个显示这一点的最小示例:
    >>> from itertools import cycle
    >>> from time import sleep
    >>> for i in cycle(range(3)):
    ... sleep(0.5)
    ... print(i)
    ...
    0
    1
    2
    0
    1
    2
    0
    我们已经论证过“将可迭代对象转换为列表”是一种可能需要遍历列表中所有元素的操作。
    因此,以下语句是一个无限循环:
    >>> list(cycle(range(3))

    关于python - 为什么我不想立即将所有可迭代对象转换为具有定义长度的内容(例如列表)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67064386/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com