15

我发现我必须在 python 中执行交换,我写了这样的东西。

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

我想这不是那么pythonic。有人知道如何在 python 中进行更优雅的交换吗?

编辑: 我认为另一个例子会表明我的怀疑

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

这是在 python 中交换的唯一可用解决方案吗?我确实搜索了很多,但没有找到一个好的答案......

4

5 回答 5

16
a, b = b, a

是一个完美的 Pythonic 成语。只要您的变量名足够短,它就简短易读。

于 2009-07-19T12:31:08.150 回答
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 "normal" indices >=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) [[不适用于负索引,虽然 - 为什么不,切片器需要如何更改才能解决这个问题?]]。但是在生产代码中使用这种奇特的方法通常会过度杀伤力并且非常没有根据,这使得事情比简单直接的方法更加模糊和难以维护。

请记住,简单胜于复杂

于 2009-07-19T16:36:43.047 回答
1

很难想象它如何变得更优雅:使用假设的内置函数......swap_sequence_elements(arr, first, second)优雅?也许,但这是在 YAGGI 领域——你不会得到它;-)——函数调用开销会/应该让你自己实现它。

你所拥有的比替代的内联方式优雅得多:

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

并且(奖励!)也更快(基于不合理的假设,即字节码ROT_TWO比 a LOAD_FASTplus a快STORE_FAST)。

于 2009-07-19T13:05:52.747 回答
1

a, b = b, a大约和你得到的一样短,它只有三个字符(除了变量名)。它就像你会得到的 Python'y

一种替代方法是通常的 use-a-temp-variable:

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

..变成..

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
于 2009-07-19T13:17:42.400 回答
-1

我想你可以利用切片符号的 step 参数来做这样的事情:

myarr[:2] = myarr[:2][::-1]

我不确定这是否更清晰或更pythonic...

于 2009-07-20T06:01:25.463 回答