簡體   English   中英

元組構造函數vs列表comp

[英]Tuple constructor vs list comp

只是說我有一個清單

a = (3, 2, 9, 4)

我想在每個數字中加一個並存儲結果,(我之后不需要操縱結果),我的第一個想法就是:

[x + 1 for x in a]

但是關於:

tuple(x + 1 for x in a)

元組意味着更快吧? 如果我不需要在此代碼更高效后更改結果? 它是如何工作的, tuple構造函數是否必須從生成器表達式中創建一個列表以提前知道大小? 提前感謝您的任何解釋。

只是timeit()

In : a = (3, 2, 9, 4)

In : f1 = lambda: [x + 1 for x in a]

In : f2 = lambda: tuple(x + 1 for x in a)

In : timeit.timeit(f1)
Out: 0.595026969909668

In : timeit.timeit(f2)
Out: 2.360887050628662

因此,似乎元組構造函數變體需要大約四倍的時間,我想因為列表推導相當優化(在cpython中)。

但讓我們仔細看看:

In : f3 = lambda: list(x + 1 for x in a)

In : timeit.timeit(f3)
Out: 2.5421998500823975

所以這與元組結構大致相同,這表明性能損失在於生成器表達式開銷。 (我們可以排除列表/元組結構,請參閱下面的編輯)

它甚至是map()列表的兩倍慢:

In : inc = partial(operator.add,1)

In : f4 = lambda:map(inc, a)

In : timeit.timeit(f4)
Out: 1.2346529960632324

我認為這實際上歸結為(cpython)實現細節,所以不要依賴於此。 無論如何 - 不要擔心性能,它只是2-4的因素,使用最好閱讀的方法。

如果您確實遇到了性能瓶頸,請發現它們之后進行調查和優化。 我敢打賭,列表操作中的因子4將是您遇到問題的最小因素。

編輯:有人提到“元組”的查找成本可能會導致速度減慢,但事實並非如此:

In : f5 = lambda: tuple([x + 1 for x in a])

In : timeit.timeit(f5)
Out: 0.7900090217590332

所以我猜這真的是生成器表達式開銷會降低速度。

dis模塊可以讓你了解代碼如何在內部執行...

dis.dis(lambda a: [x + 1 for x in a])得到...

  1           0 BUILD_LIST               0
              3 LOAD_FAST                0 (a)
              6 GET_ITER
        >>    7 FOR_ITER                16 (to 26)
             10 STORE_FAST               1 (x)
             13 LOAD_FAST                1 (x)
             16 LOAD_CONST               1 (1)
             19 BINARY_ADD
             20 LIST_APPEND              2
             23 JUMP_ABSOLUTE            7
        >>   26 RETURN_VALUE

...和dis.dis(lambda a: tuple(x + 1 for x in a))產生......

  1           0 LOAD_GLOBAL              0 (tuple)
              3 LOAD_CONST               1 (<code object <genexpr> at 0x7f62e9eda930, file "<stdin>", line 1>)
              6 MAKE_FUNCTION            0
              9 LOAD_FAST                0 (a)
             12 GET_ITER
             13 CALL_FUNCTION            1
             16 CALL_FUNCTION            1
             19 RETURN_VALUE

......但你可能無法從中推斷出太多。 如果您想知道哪個更快,請查看timeit模塊。

在大多數情況下,元組和列表之間的效率確實無關緊要。你真正關心它,你可以使用timeit進行測試。

元組和列表之間最重要的區別是元組是不可變的,列表是可以替換的。 這意味着您可以更改列表的值,但不能使用元組。 你可以散列元組但不能用列表來做。 例如

k_tuple = ('a', 'b')
k_list = ['a', 'b']
d = {}
d[k_tuple] = 'c' # It is ok
d[k_list] = 'c' #It raise exception.

更重要的是,當list作為函數的參數時,它是通過引用分配的。 當元組作為函數的參數時,它由值指定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM