2009-07-19 72 views
15

我發現我必須在Python中執行交換,並且我寫這樣的東西。Pythonic Swap?

arr[first], arr[second] = arr[second], arr[first] 

我想這不是pythonic。有人知道如何做一個交換python更elegent?

編輯: 我想其他的例子表明了我的疑慮

self.memberlist[someindexA], self.memberlist[someindexB] = self.memberlist[someindexB], self.memberlist[someindexA] 

這是在python交換唯一可用的解決方案? 我也搜索了很多,但沒有找到一個很好的答案...

+0

你不喜歡什麼?它出什麼問題了?你想要什麼可能會更短?你能否提供你認爲會更好的僞代碼? – 2009-07-19 13:46:52

+2

這是一個可怕的方式來編寫交換,不得不重複每一個表達式,但它是最好的Python可以做的。 C++的交換(a,b)是乾淨的,不重複的交換方式,但是Python不支持這種間接級別,所以它不能這樣做。只是爲了生活;每種語言都有其侷限性,這是一個小問題。 – 2009-07-19 17:29:45

回答

14

有一件事我可能會在你的示例代碼改變:如果你打算使用一些長的名稱,如self.memberlist以上再一次,它通常更容易讀取別名(「分配」)到更短的名字。因此,例如,而不是長期的,難以閱讀:

self.memberlist[someindexA], self.memberlist[someindexB] = self.memberlist[someindexB], self.memberlist[someindexA] 

你可以代碼:

L = self.memberlist 
L[someindexA], L[someindexB] = L[someindexB], L[someindexA] 

記住,Python的工作原理是引用所以L指完全相同的對象爲self.memberlist,不是副本(同樣,無論列表多長時間,分配速度都非常快,因爲它不會被複制 - 它只是一個參考)。

我不認爲任何進一步的複雜化是必要的,但當然一些奇特的人可能很容易被設想,諸如(A,B「正常」指數>=0):

def slicer(a, b): 
    return slice(a, b+cmp(b,a), b-a), slice(b, a+cmp(a,b), a-b) 

back, forth = slicer(someindexA, someindexB) 
self.memberlist[back] = self.memberlist[forth] 

我想搞清楚出於這些「高級」用途是一個不錯的自負,有益的心理練習和好玩 - 我建議感興趣的讀者,一旦總體思路清晰,重點關注那些+cmp的角色以及他們如何使三種可能性(a> b,a < b,a == b)[[不是負指數,但是 - 爲什麼不,以及切片機如何改變以解決這個問題]]。但是,在生產代碼中使用這樣一種奇特的方法通常會是過分的和毫無道理的,使得事情比簡單和直接的方法更加混亂和難以維護。

請記住,simple is better than complex

1

很難想象如何使它更優雅:使用假設的內置功能... swap_sequence_elements(arr, first, second)優雅?也許,但這是在YAGGI的領土 - 你不會得到它;-)和函數調用開銷會/應該讓你自己實現它。

你有什麼是比其他在線的方式更優雅:(!獎金)

temp = arr[first] 
arr[first] = arr[second] 
arr[second] = temp 

而且也更快(在沒有不合理的假設,即字節碼ROT_TWO快於一個LOAD_FAST加一個STORE_FAST)。

1

a, b = b, a大約是儘可能短,你會得到,這只是三個字符(除了變量名)..這是我們所Python'y,你會得到

一種替代方法是平時的使用 - 一,臨時變量:

self.memberlist[someindexA], self.memberlist[someindexB] = self.memberlist[someindexB], self.memberlist[someindexA] 

..becomes ..

temp = self.memberlist[someindexB] 
self.memberlist[someindexB] = self.memberlist[someindexA] 
self.memberlist[someindexA] = temp 

..這我覺得是混亂和不那麼 「顯而易見」

另一種方式,這也許是與長變量名有點更具可讀性:

a, b = self.memberlist[someindexA], self.memberlist[someindexB] 
self.memberlist[someindexA], self.memberlist[someindexB] = b, a 
-1

我想你可以利用切片表示法的步驟參數做這樣的事情:

myArr,該[2] = myArr,該[2] [:: - 1]

我米不知道這是更清晰或更pythonic雖然...