2009-07-19 69 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虽然...