2009-07-19 16 views
15

Descubrí que tengo que realizar un intercambio en python y escribo algo como esto.Pythonic Swap?

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

I guess this is not so pythonic. ¿Alguien sabe cómo hacer un intercambio en python más elegent?

EDIT: Creo que otro ejemplo mostrará mis dudas

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

es esta la única solución disponible para intercambio en Python? Yo buscado mucho, pero no encontró una respuesta agradable ...

+0

¿Qué te gusta? ¿Qué pasa con eso? ¿Qué le gustaría que podría ser más corto? ¿Podrías proporcionar un pseudocódigo para lo que crees que sería mejor? –

+2

Es una forma terrible de escribir un intercambio, teniendo que repetir cada expresión, pero es lo mejor que Python puede hacer. El intercambio de C++ (a, b) es la forma limpia y no repetitiva de hacer swaps, pero Python no admite ese nivel de indirección, por lo que no puede hacer eso. Solo algo con lo que vivir; cada lengua tiene sus limitaciones, y esta es menor. –

Respuesta

14

La única cosa que podría cambiar en el código de ejemplo: si se va a utilizar un nombre largo como self.memberlist sobre una vez más, a menudo es más legible para alias ("asignar") a un nombre más corto primero. Así, por ejemplo, en lugar de la larga y difícil de leer:

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

podría codificar:

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

Recuerde que Python funciona por referencia por lo que L se refiere a exactamente el mismo objeto que self.memberlist, NO es una copia (por la misma razón, la tarea es extremadamente rápida, sin importar cuánto tiempo puede durar la lista, porque de todos modos no se copia; es solo una referencia más).

No creo que ninguna complicación adicional se justifica, aunque, por supuesto, algunos de lujo fácilmente podrían ser concebidos, tales como (a, b índices "normales"): >=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] 

Creo calcular Este tipo de usos "avanzados" es una buena presunción, ejercicio mental útil y buena diversión. Recomiendo a los lectores interesados, una vez que la idea general es clara, centrarse en el papel de esos +cmp y cómo hacen que las cosas funcionen para el tres posibilidades (a> b, a < b, a == b) [[no para índices negativos, sin embargo, ¿por qué no, y cómo tendría que cambiar el slicer para arreglar esto?]]. Pero usar un enfoque tan sofisticado en el código de producción generalmente sería excesivo y bastante injustificado, haciendo que las cosas sean más oscuras y difíciles de mantener que el enfoque simple y directo.

Recuerde, simple is better than complex!

16
a, b = b, a 

Is a perfectly Pythonic idiom. Es corto y fácil de leer, siempre y cuando sus nombres de las variables son lo suficientemente corto.

+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

Es difícil imaginar cómo se podría hacer más elegante: utilizando una función hipotética incorporada ... swap_sequence_elements(arr, first, second) elegant? tal vez, pero esto está en el territorio de YAGGI; no lo vas a obtener ;-) - y la sobrecarga de la llamada a la función lo/la debería desviar de su implementación.

Lo que tenemos es mucho más elegante que la alternativa modo en línea: (bono)

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

y es más rápido también (en el supuesto de no excesivo que un código de bytes ROT_TWO es más rápido que un LOAD_FAST plus a STORE_FAST).

1

a, b = b, a es casi tan corto como te, es sólo tres personajes (aparte de los nombres de las variables) .. Es lo más Python'y como te

Una alternativa es el uso-habitual una temperatura 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 Creo que es más sucio y menos "obvia"

Otra forma, que es tal vez un poco más legible con nombres largos de variable:

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

supongo que se podría aprovechar el argumento de paso de la notación de división para hacer algo como esto:

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

I' No estoy seguro si esto es más claro o más pitónico ...

Cuestiones relacionadas