2012-06-29 36 views
21

我使用Python自從有些時候,我發現了「pythonic」的代碼方式。 我在我的代碼中使用了很多元組,其中大多數是極座標或笛卡爾座標。元組的可讀性:[0,0] vs(0,0)

,我發現自己寫的:

window.set_pos([18,8]) 

,而不是這樣的:

window.set_pos((18,8)) 

擺脫雙括號,我發現很難讀的。

看來,python自動執行從列表到元組的類型轉換,因爲我的代碼正常工作。

但這是一種很好的編碼方式嗎? 您是否有任何演示文稿提示可用於編寫可讀代碼?

非常感謝您提供的啓發性答案。

+0

我喜歡你寫它的方式,似乎更加明確定義imo。 – jamylak

+9

Python不是「做從列表到元組的類型轉換」。這是[鴨子打字](http://en.wikipedia.org/wiki/Duck_typing)在行動:大概'window.set_pos'需要一個序列的兩個項目,但不一定是2 -'tuple'(我假設因爲我不知道'window.set_pos'來自哪裏或者它是幹什麼的)。 – Chris

+9

重寫該函數以獲取兩個參數而不是一個2元組。 –

回答

25

我會小心決定避免使用元組而不是使用列表。你有沒有使用dis模塊?看什麼Python是在字節碼級做,當你做一個清單詩句做一個元組:

>>> def f(): 
...  x = [1,2,3,4,5,6,7] 
...  return x 
... 
>>> def g(): 
...  x = (1,2,3,4,5,6,7) 
...  return x 
... 
>>> import dis 
>>> dis.dis(f) 
    2   0 LOAD_CONST    1 (1) 
       3 LOAD_CONST    2 (2) 
       6 LOAD_CONST    3 (3) 
       9 LOAD_CONST    4 (4) 
      12 LOAD_CONST    5 (5) 
      15 LOAD_CONST    6 (6) 
      18 LOAD_CONST    7 (7) 
      21 BUILD_LIST    7 
      24 STORE_FAST    0 (x) 

    3   27 LOAD_FAST    0 (x) 
      30 RETURN_VALUE  
>>> 
>>> 
>>> dis.dis(g) 
    2   0 LOAD_CONST    8 ((1, 2, 3, 4, 5, 6, 7)) 
       3 STORE_FAST    0 (x) 

    3   6 LOAD_FAST    0 (x) 
       9 RETURN_VALUE 

雖然它可能永遠不會在一個GUI應用程序的問題(如你的例子似乎是),出於性能的原因你可能想要在代碼中的任何地方小心謹慎。

+1

非常感謝,你讓我信服!我真的關心性能,因爲我的應用程序不是GUI而是帶有圖形化GUI的遊戲。你是字節碼詳細的答案是真正有助於瞭解在後臺發生了什麼(我不知道DIS模塊)。 –

+1

我只是計時了兩個功能:列表版本大約需要。比元組版本增加了兩倍(對於10兆次調用,時間爲2.1秒和0.9秒)。但對於兩元素收藏,差異較小:1.6與0.9秒。 –

+2

啊,對 - 我忘記了元組文字[摺疊](http://stackoverflow.com/a/8068248/577088)。如果你傳遞文字(而不是由變量構造的元組),這可能會產生很大的差異。 – senderle

0

如果你想強調一個事實,即你的參數是一個元組,你可以明確地將其轉換:

window.set_pot(tuple([18, 18])) 
+4

這看起來好多了。 – jamylak

4

IMO使用(18,8)超過[18,8]的唯一的好處就是一個元組對象是不可改變的,你可以請確保它在傳遞的函數內不會被更改,而[18,8]可以輕鬆更改。

4

Python不會執行從列表到元組的任何自動轉換,除非set_pos方法明確地執行它。元組和列表具有非常相似的協議,因此它們傾向於在該協議內可互換。你仍然可能會破壞東西,特別是因爲元組是不可變的,可以被哈希,而列表不是。

要回答你的問題,只寫

window.set_pos((18,18)) 

適當的空間做編碼風格奇蹟。

+4

PEP-8建議不要這樣做:http://www.python.org/dev/peps/pep-0008/#pet-peeves – jamylak

+1

@jamylak:同意了,我同意PEP的建議,但這是一個特殊的這種情況可能值得例外。 –

+0

@jamylak它沒有被語言強制執行,這意味着它只是Python作者喜歡的編碼風格。這不是所有的編碼風格,並且不應該被視爲這樣。只要將它們視爲良好的指導方針,並準備在傷害可讀性時打破它們,比如在這種情況下。 – Izkata

12

你說

看來,Python是自動做從列表中的類型轉換到元組

這是值得懷疑的。由於列表和元組都是sequence types,它們都實現了許多相同的行爲,並且無論您使用的是什麼GUI庫都不需要任何列表行爲。

可能細做這在許多情況下,但是請注意,名單不佔用比元組多一點空間:

>>> sys.getsizeof((1, 2)) 
72 
>>> sys.getsizeof([1, 2]) 
88 

並可以在一些事情比元組慢:

>>> lst, tup = [1, 2], (1, 2) 
>>> def unpack(x): 
...  a, b = x 
...  
>>> %timeit unpack(tup) 
10000000 loops, best of 3: 163 ns per loop 
>>> %timeit unpack(lst) 
10000000 loops, best of 3: 172 ns per loop 

這些都是非常直到你達到更大的規模,這將無關緊要小的差異 - 在數十億電話 - S o這種權衡可能是值得的。

不過,我沒有看到人們經常這樣做。這似乎是一個很好的可讀性技巧,但在某些情況下可能會產生意想不到的後果。例如,如果你傳遞一個你打算以後再使用的列表,那麼你必須小心,不要在函數內部修改它。最後,正如J.F. Sebastian正確地指出,元組和列表傾向於意味着略有不同的東西;以非常規方式使用它們可能會否定您尋求的可讀性。

+0

謝謝你的確切答案!我知道這看起來可能有點奇怪,但我爲僅爲了可讀性目的而使用不適合的對象的想法感到興奮。我的「set_pos」方法只是將參數解包爲兩個變量,但大部分時間在循環中使用,我關心性能問題。 14 ns是否重要? –

+0

不,14ns在設置窗口位置時根本就不重要。 –

8

我嚴重懷疑元組與列表在你的情況下在性能上有明顯的區別。除非你的分析師這樣說,否則不要進行微觀優化。可讀性是重中之重。

listtuple都是sequence types。 (請參閱Tuples have structure, lists have order)。位置是具有x,y屬性的單個對象。

可視列表在這種情況下可能更容易閱讀。

無論你選擇的只是是一致的

檢查是否window支持以下功能:

window.pos = 18, 8 

來實現它的可能方式是使pos一個property並綁定set_pos()作爲二傳手。

+2

對於元組與列表的語義而言,+1幾乎總是決定使用的因素。 – FogleBird