2010-11-18 232 views
4

[Python的3.1]的Python:可變長度元組

我的設計概念,即元組應當是已知長度的以下(見this comment)和未知長度的元組應當使用列表在大多數情況下更換。我的問題是我應該在什麼情況下偏離這個規則?

例如,我知道元組比字符串更快地創建字符串和數字字面值(請參閱another comment)。所以,如果我有性能關鍵的代碼,其中有很多計算,如sumproduct(tuple1, tuple2),我是否應該重新定義它們在列表中工作,儘管性能受到影響? (sumproduct((x, y, z), (a, b, c))被定義爲x * a + y * b + z * c,其參數未指定,但長度相等)。

那麼使用def f(*x)時由Python自動構建的元組呢?我認爲這不是我每次使用它時都要列出的東西。

順便說一句,是(x, y, z)更快創建比[x, y, z](變量而不是文字)?

回答

10

在我看來,元組和列表之間唯一有趣的區別是列表是可變的,元組不是。人們提到的其他區別似乎完全屬於我:元組就像結構體,列表就像數組(這是「元組應該是已知長度」的來源)。但結構如何與不變性保持一致?事實並非如此。

唯一重要的區別是語言的區別:可變性。如果您需要修改對象,請使用列表。如果您需要散列對象(作爲字典中的鍵或集合中的元素),那麼您需要它是不可變的,因此請使用元組。而已。

0

元組更簡單,然後列表。把它們用在任何你可以忍受它們不可變的地方。

3

我總是爲作業使用最合適的數據結構,並且不用擔心元組是否會在這裏或那裏爲我節省半毫秒。對代碼進行預混淆通常不會得到回報。如果代碼運行速度太慢,以後可以隨時對其進行概要分析,並在代碼重要的地方更改.01%的代碼。

你所談論的所有事情都與python版本及其運行的硬件的實現有關。你總是可以用這些東西來計時,看看你的機器上會有什麼。

這是一個常見的例子,python中的'舊的不可變字符串串聯緩慢'。大約在10年前,這是真的,然後他們改變了實施2.4或2.5。如果你做自己的測試,他們現在的運行速度比列表快,但人們仍然相信今天仍然存在,並使用實際上運行速度較慢的愚蠢構造!

+0

也許你說在此之前,另一些則沒有,你應該做一些剖析。嘗試在timeit中從數字和字符串文字構造元組和列表,並查看會發生什麼。另外,關於混淆python的所有內容是什麼?元組如何混淆任何東西?似乎對我完全清楚。 – aaronasterling 2010-11-18 10:30:04

+0

如果在代碼使用列表更清晰的情況下使用元組,那麼它就是混淆代碼。一個元組本身可能對任何人都是清楚的,但它是一塊更大的代碼塊。閱讀Ned Batchelder的回答。如果你需要一個使用它。如果你需要其他用途。 「常量時間」O(1)中構造元組和列表。那麼它是否值得讓一點速度妥協設計? – 2010-11-18 22:55:25

2

在什麼情況下我應該偏離那個[元組應該是已知長度]規則?

無。

這是一個的含義的問題。如果一個對象具有基於固定數量元素的含義,那麼它就是一個元組。 (x,y)座標,(c,m,y,k)顏色,(lat,lon)位置等等。

一個元組基於一般問題域以及問題的具體細節,具有固定數量的元素。

設計元組數不確定的元組毫無意義。我們什麼時候從(x,y)切換到(x,y,z),然後切換到(x,y,z,w)座標?不是簡單地將一個值串聯起來,就好像它是一個列表?如果我們從二維座標移動到三維座標,通常會有一些相當奇特的數學來繪製座標系。不要將元素附加到列表中。

從(r,g,b)顏色移到其他顏色是什麼意思?什麼是rgb系統的第四種顏色?對於這個問題,cmyk系統中的第五個顏色是什麼?

元組不要更改大小。

*args是一個元組,因爲它是不可變的。是的,它的參數數量是無限的,但對於已知的已定義大小的元組來說,這是一個罕見的反例。如何處理不確定長度的元組。這個反例非常深刻,我們有兩個選擇。

  1. 拒絕這樣一個想法,即元組是固定長度的,並受到問題的限制。由於這個反例,(x,y)座標和(r,g,b)顏色的想法完全沒有價值,也是錯誤的。固定長度的元組?決不。

  2. 始終將所有*args轉換爲列表,以始終具有不拘一格的符合設計原則的模糊程度。隱瞞名單?總是。

我喜歡全部或全部的選擇,因爲它們使得軟件工程變得如此簡單和不假思索。

也許,在這些角落案例中,這裏有一小部分「這需要思考」。一小塊廢料。

是的,*args是一個元組。是的,它的長度不確定。是的,這是一個反例,「由問題域固定」被「簡單不變」所束縛。

由於不同的原因,這導致我們在序列不可變的情況下的第三種選擇。你永遠不會改變它,所以可以成爲無限大的元組。在甚至更罕見的情況下,由於您將它視爲堆棧或隊列,因此您彈出的值爲*args,那麼您可能希望將其列出。但是我們不能預先解決所有可能的問題。

有時需要思考。


當你在做設計時,你設計一個元組是有原因的。對您的數據施加一個有意義的結構。固定長度的元素數量?元組。可變數量的元素(即可變)?名單。

+0

性能是否太小而不必擔心?我應該怎樣處理Python自己的無限長元組(當參數被打包成一個元組時) - 我是否應該立即將它強制轉換爲列表? – max 2010-11-18 06:55:25

+0

我可以想到至少有一個反例與你的主張有關。 '* args'。這是一個元組,我不知道它會持續多久。我認爲你不會想出比這更「pythonic」的反例。 – aaronasterling 2010-11-18 10:32:49

+1

@max:「性能是否太小而不必擔心?」是。這是**的意思**。在這種情況下,性能並不重要。如果你需要更多的速度,找到正確的算法。如果你可以**證明**你有正確的算法,並且你可以**證明** Python的實現太慢,切換到C的那一件事。 – 2010-11-18 10:59:14

0

在這種情況下,您應該考慮使用numpy和numpy數組。

有一些開銷轉換,並從numpy的數組,但如果你正在做一堆計算,這將是更快