J'écris un petit programme pour créer une liste de permutations. J'ai lu sur le algorithme sur Wikipedia .
Mon algorithme prend essentiellement une liste initialement triée de chiffres et le permute en place. Il ajoute ensuite cette nouvelle permutation à une liste. Lorsque toutes les permutations sont trouvées, il renvoie la liste des listes contenant toutes les permutations. Il est très bon d'imprimer les résultats escomptés, mais lorsque j'essaie d'ajouter ces résultats à une liste, les choses vont un peu drôle. P>
J'ai remarqué que chaque fois que je trouve la prochaine permutation et que je l'annonce, les éléments de liste précédents sont mis à jour à la nouvelle permutation. Ainsi, à la fin de tout cela, ce qui est retourné est une liste contenant un tas de copies de la même permutation (exactement la dernière permutation). P>
J'ai lu que Python passe par valeur, passe par référence et j'ai également lu que ce n'est pas non plus. Je ne suis pas assez intelligent pour discuter avec l'une de ces personnes, mais je me demande pourquoi mon programme le fait et comment la remédier à: P>
def lexi_order(nums): permutations = [] length = len(nums) while True: # find largest index i such that nums[i] < nums[i + 1] exists = False for j, elem in enumerate(nums): # check if last element if j == length - 1: break if elem < nums[j + 1]: i = j exists = True if not exists: break # find largest index k, such that i < k AND nums[i] < nums[k] for j in range(i + 1, length): if nums[j] > nums[i]: k = j # swap order of nums[i] and nums[k] nums[i], nums[k] = nums[k], nums[i] # reverse order of elements starting at position i+1 to_reverse = nums[i+1:][::-1] nums[i+1::] = to_reverse permutations.append(nums) print(permutations) return permutations
3 Réponses :
Lorsque vous appendez nums code> à
permutations code>, vous devez l'ajouter une référence à celle-ci, ne copiant pas toutes les données sur. Lorsque vous modifiez
nums code>, il est modifié partout. Python passe par référence. Si vous modifiez une variable (à ne pas être confondu avec la réaffectation), ce changement sera reflété partout. P>
Vous devez être vraiment prudent avec la terminologie ici, car la réaffectation d'un élément d'une liste sera réellement Changer i> la liste.
Vous modifiez l'entrée ( nums code>) en place chaque itération via la boucle, puis vous continuez à ajouter une référence à l'entrée à
permutations code>. Pour le corriger, effectuez une copie de
nums code> au début de la boucle et utilisez-le au lieu de l'original partout dans l'intérieur. P>
Donc, j'ai lu que si je fais quelque chose comme temp_list = nums code>, que je donne simplement le même objet deux noms. Je lis que si je fais quelque chose à
temp_list code>, il sera reflété dans
nums code> aussi. Un exemple est donné ici: Jeffknupp.com / Blog / 2012/11/13 / ... . J'ai testé cela pour voir si c'était vrai et cela a fonctionné. Alors, comment puis-je faire une "copie" distincte?
Vous devez effectuer une copie des nums code> code>, sinon vous travaillez sur la référence transmise. E.G.
def lexi_order(nums): permutations = [] nums = list(nums) # We are now working on a copy, and won't mutate the original whatsoever. length = len(nums) ...
Ce n'est pas suffisant. La boucle nécessite également des copies sur chaque étape d'itération.
Vous ne copiez jamais
nums code> - il n'y a que un seul objet i> que vous modifiez et ajoute à plusieurs reprises à
permutations code>.
Python est toujours transmis par référence. Ils aident les utilisateurs à Parfois i> éviter les bugs liés à la référence de référence consiste à faire certains types courants immuables (int, flotteur, str, tuple). Un type immuable aide, car une fois votre variable référencée une instance d'un type immuable, vous pouvez être certain que la valeur qu'il est référencée ne changera pas. Vous devez être conscient de quels types sont et ne sont pas immuables afin d'écrire un code intelligent en Python.
@Mistermiyagi Oui, d'une manière. Il va bien avec l'une des réponses ci-dessous qui indique que je dois faire une copie pour chaque nouvelle permutation. Cependant, une pièce est manquante pour moi, qui est dans mon commentaire à cette réponse: disons que je dis
temp_nums = nums code>, puis selon votre lien et que l'article que j'ai lu, je ne fais pas une copie. Donc, je dois apprendre à copier quelque chose au lieu de lui donner de nouveaux noms.
@HYMNSFORDISCO HMM, cela a du sens. Doit être pourquoi c'est ma première fois dans ce type de problème. Je passais par référence tout au long, mais l'immuabilité des variables que j'utilisais m'a fait penser que je faisais tout en valeur. Merci!
Calling
Liste (My_List) CODE> est le moyen standard de faire une copie peu profonde d'une liste. "Copier" Quelque chose n'est pas aussi simple que vous pouvez penser. Recherchez des ressources sur la copie de VS peu profonde en Python et de copier des objets avec le module code> Copier Copie>