415 votes

Existe-t-il une méthode standardisée pour permuter deux variables en Python ?

En Python, j'ai vu deux valeurs de variables interverties en utilisant cette syntaxe :

left, right = right, left

S'agit-il de la manière standard d'échanger les valeurs de deux variables ou existe-t-il un autre moyen par lequel deux variables sont par convention le plus souvent échangées ?

1 votes

@eyquem : il s'agit simplement de savoir si ordre d'évaluation est défini par le langage pour une affectation de tuple/liste. Python le fait, la plupart des langages plus anciens ne le font pas.

0 votes

Hrmm C++ a swap(a[i], a[k]) pourquoi ne pouvons-nous pas avoir quelque chose comme ça pour Python.

2 votes

@Nils Parce qu'en Python, l'affectation est une crénelage opération alors que dans l'affectation C++ à une référence est un remplacement opération. Par conséquent, en Python, vous ne pouvez pas remplacer les valeurs des arguments passés à une fonction comme en C++ (vous pouvez seulement les muter). Voir Copie et comparaison : Problèmes et solutions de Grogono et Sakkinen pour une explication de ces termes.

0voto

LogicalBranch Points 3584

Pour contourner les problèmes expliqués par eyquem vous pouvez utiliser l'option copy pour retourner un tuple contenant des copies (inversées) des valeurs, via une fonction :

from copy import copy

def swapper(x, y):
  return (copy(y), copy(x))

Même fonction qu'un lambda :

swapper = lambda x, y: (copy(y), copy(x))

Puis, attribuez-leur les noms souhaités, comme ceci :

x, y = swapper(y, x)

NOTE : si vous le vouliez, vous pourriez importer/utiliser deepcopy au lieu de copy .

0voto

edW Points 27

Cette syntaxe est une façon standard d'échanger des variables. Cependant, nous devons faire attention à l'ordre lorsqu'il s'agit d'éléments qui sont modifiés et ensuite utilisés dans les éléments de stockage suivants de l'échange.

L'utilisation de tableaux avec un index direct ne pose aucun problème. Par exemple :

def swap_indexes(A, i1, i2):
      A[i1], A[i2] = A[i2], A[i1]
      print('A[i1]=', A[i1], 'A[i2]=', A[i2])
      return A

  A = [0, 1, 2, 3, 4]
  print('For A=', A)
  print('swap indexes 1, 3:', swap_indexes(A, 1, 3))

Nous donne :
("Pour A=", [0, 1, 2, 3, 4])
('A[i1]=', 3, 'A[i2]=', 1)
('swap indexes 1, 3:', [0, 3, 2, 1, 4])

Cependant, si nous modifions le premier élément de gauche et l'utilisons dans le deuxième élément de gauche comme un index, cela provoque un mauvais swap.

def good_swap(P, i2):
    j = P[i2]
    #Below is correct, because P[i2] is modified after it is used in P[P[i2]]
    print('Before: P[i2]=', P[i2], 'P[P[i2]]=', P[j])
    P[P[i2]], P[i2] = P[i2], P[P[i2]]
    print('Good swap: After P[i2]=', P[i2], 'P[P[i2]]=', P[j])
    return P

def bad_swap(P, i2):
    j = P[i2]
    #Below is wrong, because P[i2] is modified and then used in P[P[i2]]
    print('Before: P[i2]=', P[i2], 'P[P[i2]]=', P[j])
    P[i2], P[P[i2]] = P[P[i2]], P[i2]
    print('Bad swap: After P[i2]=', P[i2], 'P[P[i2]]=', P[j])
    return P

P = [1, 2, 3, 4, 5]
print('For P=', P)
print('good swap with index 2:', good_swap(P, 2))
print('------')
P = [1, 2, 3, 4, 5]
print('bad swap with index 2:', bad_swap(P, 2))

("Pour P=", [1, 2, 3, 4, 5])
("Avant : P[i2]=", 3, "P[P[i2]]=", 4)
('Bon échange : Après P[i2]=', 4, 'P[P[i2]]=', 3)
('good swap with index 2:', [1, 2, 4, 3, 5])

("Avant : P[i2]=", 3, "P[P[i2]]=", 4)
('Bad swap : After P[i2]=', 4, 'P[P[i2]]=', 4)
('bad swap with index 2:', [1, 2, 4, 4, 3])

Le mauvais échange est incorrect car P[i2] est 3 et nous nous attendons à ce que P[P[i2]] soit P[3]. Cependant, P[i2] est d'abord changé en 4, donc le P[P[i2]] suivant devient P[4], ce qui écrase le 4ème élément plutôt que le 3ème.

Le scénario ci-dessus est utilisé en permutations. Un bon et mauvais échange plus simple serait :

#good swap:
P[j], j = j, P[j]
#bad swap:
j, P[j] = P[j], j

-3voto

u-betcha Points 1

Vous pouvez combiner tuple y XOR des échanges : x, y = x ^ x ^ y, x ^ y ^ y

x, y = 10, 20

print('Before swapping: x = %s, y = %s '%(x,y))

x, y = x ^ x ^ y, x ^ y ^ y

print('After swapping: x = %s, y = %s '%(x,y))

o

x, y = 10, 20

print('Before swapping: x = %s, y = %s '%(x,y))

print('After swapping: x = %s, y = %s '%(x ^ x ^ y, x ^ y ^ y))

Utilisation de lambda :

x, y = 10, 20

print('Before swapping: x = %s, y = %s' % (x, y))

swapper = lambda x, y : ((x ^ x ^ y), (x ^ y ^ y))

print('After swapping: x = %s, y = %s ' % swapper(x, y))

Sortie :

Before swapping: x =  10 , y =  20
After swapping: x =  20 , y =  10

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X