2 个列表元素的 Pythonic 交换

发布于 2024-07-28 23:27:29 字数 389 浏览 4 评论 0原文

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

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

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

编辑: 我认为另一个例子会显示我的疑问:

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

这是 python 中交换的唯一可用解决方案吗?

I found that I have to perform a swap in python and I write something like this:

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

I suppose this is not so pythonic. Does somebody know how to do a swap in python more elegant?

EDIT:
I think another example will show my doubts:

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

is this the only available solution for swap in python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

橪书 2024-08-04 23:27:29
a, b = b, a

是一个完美的 Python 习语。 它很短并且可读,只要你的变量名足够短。

a, b = b, a

Is a perfectly Pythonic idiom. It is short and readable, as long as your variable names are short enough.

唠甜嗑 2024-08-04 23:27:29

我可能会在您的示例代码中更改一件事:如果您要反复使用一些长名称,例如 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

请记住,简单胜于复杂

The one thing I might change in your example code: if you're going to use some long name such as self.memberlist over an over again, it's often more readable to alias ("assign") it to a shorter name first. So for example instead of the long, hard-to-read:

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

you could code:

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

Remember that Python works by-reference so L refers to exactly the same object as self.memberlist, NOT a copy (by the same token, the assignment is extremely fast no matter how long the list may be, because it's not copied anyway -- it's just one more reference).

I don't think any further complication is warranted, though of course some fancy ones might easily be conceived, such as (for 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]

I think figuring out these kinds of "advanced" uses is a nice conceit, useful mental exercise, and good fun -- I recommend that interested readers, once the general idea is clear, focus on the role of those +cmp and how they make things work for the three possibilities (a>b, a<b, a==b) [[not for negative indices, though -- why not, and how would slicer need to change to fix this?]]. But using such a fancy approach in production code would generally be overkill and quite unwarranted, making things murkier and harder to maintain than the simple and straightforward approach.

Remember, simple is better than complex!

烟雨扶苏 2024-08-04 23:27:29

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

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

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

并且(奖励!)也更快(基于字节码 ROT_TWOLOAD_FAST 更快的合理假设代码>加上STORE_FAST)。

It's difficult to imagine how it could be made more elegant: using a hypothetical built-in function ... swap_sequence_elements(arr, first, second) elegant? maybe, but this is in YAGGI territory -- you aren't going to get it ;-) -- and the function call overhead would/should put you off implementing it yourself.

What you have is much more elegant than the alternative in-line way:

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

and (bonus!) is faster too (on the not unreasonable assumption that a bytecode ROT_TWO is faster than a LOAD_FAST plus a STORE_FAST).

裸钻 2024-08-04 23:27:29

a, b = b, a 大约是你能得到的最短的,它只有三个字符(除了变量名)..它和 Python 一样,你会得到

一个替代方案是通常的 use-a-temp-variable:

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

a, b = b, a is about as short as you'll get, it's only three characters (aside from the variable names).. It's about as Python'y as you'll get

One alternative is the usual use-a-temp-variable:

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

..which I think is messier and less "obvious"

Another way, which is maybe a bit more readable with long variable names:

a, b = self.memberlist[someindexA], self.memberlist[someindexB]
self.memberlist[someindexA], self.memberlist[someindexB] = b, a
芸娘子的小脾气 2024-08-04 23:27:29

我想你可以利用切片表示法的步骤参数来做这样的事情:

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

我不确定这是否更清晰或更Pythonic。 。

I suppose you could take advantage of the step argument of slice notation to do something like this:

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

I'm not sure this is clearer or more pythonic though...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文