2009-07-19 19 views
15

Ho scoperto che devo eseguire uno scambio in python e scrivo qualcosa del genere.Scambio Pythonic?

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

Suppongo che questo non sia così pirotecnico. Qualcuno sa come fare uno scambio in pitone più elegante?

EDIT: Penso che un altro esempio mostra i miei dubbi

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

è questa l'unica soluzione disponibile per lo swap in Python? ho cercato un sacco, ma non ho trovato una risposta bella ...

+0

Cosa non ti piace? Che cosa c'è che non va? Cosa ti piacerebbe che potrebbe essere più breve? Potresti fornire uno pseudo-codice per quello che pensi sarebbe meglio? –

+2

È un modo terribile di scrivere uno scambio, dover ripetere ogni espressione, ma è il migliore che Python possa fare. Lo swap di C++ (a, b) è il modo pulito e non ripetitivo di fare swap, ma Python non supporta quel livello di indirezione, quindi non può farlo. Solo qualcosa con cui vivere; ogni lingua ha i suoi limiti, e questo è minore. –

risposta

14

L'unica cosa che potrebbe cambiare nel codice di esempio: se avete intenzione di utilizzare un nome lungo come self.memberlist over ancora una volta, è spesso più leggibile in alias ("assegna") a un nome più breve prima. Così, per esempio, al posto del lungo, duro da leggere:

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

si potrebbe codice:

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

Ricordate che Python opere di riferimento in modo L si riferisce alla esattamente lo stesso oggetto come self.memberlist, NON una copia (per lo stesso motivo, l'assegnazione è estremamente veloce, non importa per quanto tempo può essere la lista, perché non è comunque copiata - è solo un altro riferimento).

Non che qualsiasi ulteriore complicazione è garantito, anche se naturalmente alcuni tra quelli di fantasia potrebbero facilmente essere concepiti come (a, b "normali" indici >=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] 

Credo capire questo tipo di usi "avanzati" è una bella presunzione, esercizio mentale utile e buon divertimento - raccomando che i lettori interessati, una volta che l'idea generale sia chiara, si concentrino sul ruolo di quelli +cmp e su come fanno funzionare le cose per il tre possibilità (a> b, a < b, a == b) [[non per gli indici negativi, però - perché no, e in che modo l'affettatrice deve cambiare per risolvere questo problema?]]. Ma l'uso di un tale approccio di fantasia nel codice di produzione sarebbe generalmente eccessivo e abbastanza ingiustificato, rendendo le cose più oscure e difficili da mantenere rispetto all'approccio semplice e diretto.

Ricorda, simple is better than complex!

16
a, b = b, a 

Is a perfectly Pythonic idiom. È breve e leggibile, fino a quando i vostri nomi di variabili sono abbastanza brevi.

+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

È difficile immaginare come potrebbe essere reso più elegante: utilizzando un'ipotetica funzione integrata ... swap_sequence_elements(arr, first, second) elegante? forse, ma questo è nel territorio YAGGI - non lo capirai ;-) - e la funzione chiamata overhead dovrebbe/dovrebbe impedirti di implementarla tu stesso.

Quello che hai è molto più elegante che l'alternativa modo in linea: (! Bonus)

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

ed è troppo veloce (sul presupposto non irragionevole che un bytecode ROT_TWO è più veloce di un LOAD_FAST più a STORE_FAST).

1

a, b = b, a è quanto di più breve, come si arriva, è solo tre personaggi (a parte i nomi delle variabili) .. E 'quanto di più Python'y come avrete

Un'alternativa è il solito uso- a-temp-variabile:

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 

..che credo sia Messier e meno "ovvio"

Un altro modo, che è forse un po 'più leggibile con nomi di variabili lunghi:

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

Suppongo che si possa approfittare dell'argomento fase della fetta notazione per fare qualcosa di simile:

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

I' Non sono sicuro che sia più chiaro o più pitonico ...