2009-07-19 38 views
15

Tôi thấy rằng tôi phải thực hiện một trao đổi trong python và tôi viết một cái gì đó như thế này.Hoán đổi Pythonic?

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

Tôi cho rằng điều này không quá nhiệt tình. Có ai biết làm thế nào để làm một trao đổi trong python sang trọng hơn?

EDIT: Tôi nghĩ rằng một ví dụ khác sẽ hiển thị những nghi ngờ của tôi

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

đây là giải pháp duy nhất có sẵn cho swap trong python? tôi đã tìm kiếm rất nhiều nhưng không tìm thấy một câu trả lời tốt đẹp ...

+0

Những gì bạn không thích? Có gì sai với nó? Những gì bạn muốn mà có thể có thể ngắn hơn? Bạn có thể cung cấp mã giả cho những gì bạn cho là tốt hơn không? –

+2

Đó là một cách khủng khiếp để viết một trao đổi, phải lặp lại mọi biểu thức, nhưng đó là Python tốt nhất có thể làm. Hoán đổi của C++ (a, b) là cách làm sạch, không lặp đi lặp lại để thực hiện hoán đổi, nhưng Python không hỗ trợ mức độ gián đoạn đó, vì vậy nó không thể làm điều đó. Chỉ cần một cái gì đó để sống với; mọi ngôn ngữ đều có những hạn chế của nó, và đây là một hạn chế nhỏ. –

Trả lời

14

Một trong những điều tôi có thể thay đổi trong mã ví dụ của bạn: nếu bạn đang sử dụng một số tên dài như self.memberlist trên một lần nữa, nó thường dễ đọc hơn đối với bí danh ("gán") cho một tên ngắn hơn trước. Vì vậy, ví dụ thay vì dài, khó đọc:

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

bạn có thể mã:

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

Hãy nhớ rằng Python hoạt động bằng cách tham khảo để L đề cập đến chính xác cùng một đối tượng như self.memberlist, KHÔNG phải là một bản sao (bởi cùng một mã thông báo, nhiệm vụ là cực kỳ nhanh chóng không có vấn đề bao lâu danh sách có thể được, bởi vì nó không được sao chép anyway - nó chỉ là một tài liệu tham khảo nhiều hơn).

Tôi không nghĩ rằng bất kỳ biến chứng hơn nữa là bảo hành, mặc dù tất nhiên một số những người ưa thích có thể dễ dàng được quan niệm, chẳng hạn như (đối với a, b chỉ số "bình thường" >=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] 

Tôi nghĩ tìm những cách sử dụng "nâng cao" này là một khái niệm tốt, tập thể dục tinh thần hữu ích và vui vẻ - tôi khuyên người đọc quan tâm, khi ý tưởng chung rõ ràng, tập trung vào vai trò của những người +cmp đó và cách họ làm mọi thứ ba khả năng (a> b, a < b, a == b) [[không cho chỉ số tiêu cực, mặc dù - tại sao không, và slicer sẽ cần thay đổi để sửa lỗi này như thế nào?]]. Nhưng việc sử dụng một cách tiếp cận ưa thích trong mã sản xuất nói chung là quá mức cần thiết và khá không chính đáng, làm cho mọi thứ trở nên khó khăn hơn và khó duy trì hơn so với cách tiếp cận đơn giản và dễ hiểu.

Hãy nhớ rằng, simple is better than complex!

16
a, b = b, a 

Is a perfectly Pythonic idiom. Đó là ngắn và có thể đọc được, miễn là tên biến của bạn là đủ ngắn.

+0

http://www.google.co.il/search?q=python+swap&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a –

1

Thật khó để tưởng tượng làm thế nào nó có thể được thực hiện thanh lịch hơn: sử dụng một chức năng giả định được xây dựng trong ... swap_sequence_elements(arr, first, second) thanh lịch? có lẽ, nhưng điều này là trong lãnh thổ YAGGI - bạn sẽ không nhận được nó ;-) - và chức năng cuộc gọi trên đầu sẽ/nên đưa bạn ra thực hiện nó cho mình.

gì bạn có là nhiều hơn nữa tao nhã hơn thay thế trong dòng cách: (! Bonus)

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

và vận hành nhanh quá (trên giả định không hợp lý rằng một bytecode ROT_TWO là nhanh hơn so với một LOAD_FAST cộng a STORE_FAST).

1

a, b = b, a khoảng càng ngắn càng bạn sẽ nhận được, đó là chỉ có ba nhân vật (ngoài những cái tên biến) .. Đó là về như Python'y như bạn sẽ nhận được

Một thay thế là use- thông thường một-temp-biến:

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 

đồi khế, đồi tôi nghĩ là Messier và ít "rõ ràng"

Một cách khác, đó là có thể là một chút dễ đọc hơn với tên biến dài:

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

Tôi cho rằng bạn có thể tận dụng lợi thế của các đối số bước của ký hiệu lát để làm một cái gì đó như thế này:

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

tôi m không chắc chắn điều này là rõ ràng hơn hoặc nhiều hơn pythonic mặc dù ...

Các vấn đề liên quan