Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

intervertir une liste d' objets

+2 votes

je cherche une façon pythonique et directe pour intervertir une liste d' objets graphiques
(éléments clickables ou non de la librairie thorpy / pygame).

par exemple :
mesboutons = [bouton0,bouton1,bouton2,bouton4,bouton3,bouton5]
y'a t il une meilleure façon que ceci:

tmp_obj = mesboutons[3]
mesboutons[3] = mesboutons[4]
mesboutons[4] = tmp_obj

je cherche une formule du genre

mesboutons.intervert(3,4)

La méthode insert expose au même problème, je veux éviter des copies inutiles, en c++ y'aurait une manip sur les pointeurs.
Pour le jour où je manipule des objets lourds.

demandé 22-Jan-2018 par buffalo974 (2,956 points)

Note: il n'y a pas de copie dans le code que tu donnes. Aucun souci avec des objets lourds donc, c'est seulement les références qui sont échangées.

3 Réponses

+5 votes
 
Meilleure réponse

Tu peux faire :

mesboutons[3], mesboutons[4] = mesboutons[4], mesboutons[3]

Swap en une seule opération, c'est pythonique.

répondu 23-Jan-2018 par Tiger-222 (1,200 points)
sélectionné 23-Jan-2018 par buffalo974
+1 vote

Utilise des slices :

>>> mesboutons = ['bouton0', 'bouton1', 'bouton2', 'bouton4', 'bouton3', 'bouton5']
>>> mesboutons[3:5] = mesboutons[4:2:-1]
>>> mesboutons
['bouton0', 'bouton1', 'bouton2', 'bouton3', 'bouton4', 'bouton5']
répondu 24-Jan-2018 par Simpom

y'a t il un avantage quelconque en passant par les slices, car je trouve
cette écriture moins intuitive ?

Pour échanger deux valeurs, pas d'intérêt à mon sens. Cela devient plus intéressant pour changer l'ordre de plus de valeurs.

+2 votes

La bonne réponse est celle de Tiger-222.
Néanmoins, si le nombre d'objets à inverser est grand ou variable, l'énumération est peu pratique, d'où la réponse de Simpom.

Voici une variante que j'aime bien : elle permet d'implémenter le comportement généralisé de ta fonction hypothétique intervert.

>>> l = [1, 2, 3, 4, 5]
>>> l[2:5] = reversed(l[2:5])
>>> l
[1, 2, 5, 4, 3]

La fonction apply_to_slice se déduit :

def apply_to_slice(it, start, end, function):
    it[start:end] = function(it[start:end])
    return it  # for convenience

def intervert(it, start, end):
    return apply_to_slice(it, start, end, reversed)
répondu 17-Fev-2018 par lucas (2,340 points)

hmmm si on fait comme ça et que la liste [start:end] fait plus de trois éléments ça va poser problème du fait que les éléments "centraux" seront inversés:

>>> l = [1, 2, 3, 4, 5]
>>> l[1:5] = reversed(l[1:5])
>>> l
[1, 5, 4, 3, 2]

ça peut servir en effet, je garde ça sous le coude

...