J'ai un problème lors de l'ajout de valeur dans le dictionnaire imbriqué en utilisant les mêmes clés et la valeur est toujours affichée avec la même valeur, le fait est que je veux mettre à jour l'événement de valeur, les clés sont les mêmes. Cet algorithme est la base de l'algorithme Artificial Fish Swarm
# example >> fish_template = {0:{'weight':3.1,'visual':2,'step':1},1:'weight':3,'visual':4,'step':2}} fish = {} fish_value = {} weight = [3.1, 3, 4.1, 10] visual = [2, 4, 10, 3] step = [1, 2, 5, 1.5] len_fish = 4 for i in range(0,len_fish): for w, v, s in zip(weight, visual, step): fish_value["weight"] = w fish_value["visual"] = v fish_value["step"] = s fish[i] = fish_value print("show fish",fish)
Je m'attends à ce que le résultat soit comme fish_template, mais ce n'est pas le cas. Les valeurs des clés 'weight', 'visual', 'step' sont toujours les mêmes avec des valeurs de 0, 1, 2 et 3. Une solution?
3 Réponses :
Je ne suis pas sûr de bien comprendre ce que vous essayez de faire ici, mais le problème est la dernière ligne de votre boucle for intérieure. Vous faites une boucle sur i
dans la boucle principale, puis la boucle interne définit fish [i]
plusieurs fois. En conséquence, toutes vos fish_value seront identiques.
oui, j'ai déjà essayé d'imprimer à l'intérieur, la valeur est affichée, mais quand j'obtiens de la dernière boucle, la dernière valeur n'est pas toute la valeur après l'ajout
Le problème est avec fish [i]
, vous avez simplement créé un dict
avec le même élément: fish_value
. Python ne génère pas de nouvelle mémoire pour le même nom de variable, donc toutes vos clés dict pointent vers la même valeur = fish_value
, qui est écrasée et toutes vos valeurs dict prennent le dernier état de fish_value
. Pour surmonter cela, vous pouvez faire ce qui suit:
fish = dict((i, {"weight": weight[i], "visual": visual[i], "step": step[i]}) for i in range(len_fish))
Comme @Error l'a mentionné, la boucle for peut être remplacée par cette one-liner:
fish = {} weight = [3.1, 3, 4.1, 10] visual = [2, 4, 10, 3] step = [1, 2, 5, 1.5] len_fish = 4 for i in range(0, len_fish): fish[i]= {"weight": weight[i], "visual": visual[i], "step": step[i]} print("show fish", fish)
Vous pourriez une ligne ceci avec la compréhension du dictionnaire.
@ Error-SyntacticalRemorse: Je montre la compréhension d'une ligne ci-dessous. Utiliser une classe personnalisée, mais ce n'est pas nécessaire.
En raison de aliasing ; la ligne fish [i] = fish_value
est une mauvaise pratique, fish_value
est écrasée à chaque fois que vous bouclez; alors fish [i] = fish_value
attribue simplement une copie peu profonde dans fish [i]
, ce qui n'est pas ce que vous voulez.
Mais vraiment, vous pouvez éviter la boucle avec une compréhension de dict .
Quoi qu'il en soit, une meilleure pratique de codage consiste à déclarer votre propre classe Fish
avec le poids des membres , visuel, étape
, comme ci-dessous. Notez comment:
zip ()
pour combiner les listes w, v, s
séparées en un tuple de liste. * wvs
décompresse chaque tuple en trois valeurs distinctes ('weight', 'visual', 'step'). Cela s'appelle décompression de tuple , cela vous évite d'avoir besoin d'une autre boucle, ou indexation. __repr __ ()
personnalisée (avec art ASCII facultatif) rend chaque objet lisible par l'utilisateur. (Strictement, nous devrions remplacer __str__
plutôt que __repr__
, mais cela fonctionne) Code:
class Fish(): def __init__(self, weight=None, visual=None, step=None): self.weight = weight self.visual = visual self.step = step def __repr__(self): """Custom fishy __repr__ method, with ASCII picture""" return f'<º)))< ð [ Weight: {self.weight}, visual: {self.visual}, step: {self.step} ]' # define whatever other methods you need on 'Fish' object... # Now create several Fish'es... swarm = [ Fish(*wvs) for wvs in zip([3.1, 3, 4.1, 10], [2, 4, 10, 3], [1, 2, 5, 1.5]) ] # zip() function combines the lists into a tuple-of-list. `*wvs` unpacks each tuple into three separate values ('weight', 'visual', 'step') # See what we created... >>> swarm [<º)))< ð [ Weight: 3.1, visual: 2, step: 1 ], <º)))< ð [ Weight: 3, visual: 4, step: 2 ], <º)))< ð [ Weight: 4.1, visual: 10, step: 5 ], <º)))< ð [ Weight: 10, visual: 3, step: 1.5 ]] # ... or for prettier output... >>> for f in swarm: print(f) <º)))< ð [ Weight: 3.1, visual: 2, step: 1 ] <º)))< ð [ Weight: 3, visual: 4, step: 2 ] <º)))< ð [ Weight: 4.1, visual: 10, step: 5 ] <º)))< ð [ Weight: 10, visual: 3, step: 1.5 ]
Les classes doivent strictement remplacer leur __str__
plutôt que __repr__
, mais cela fonctionne à moins que vous ne souhaitiez pickle
votre Fish
.. . ;-)
Chose sûre. Lorsque vous accédez à 15 réputation, vous pouvez voter pour les réponses que vous avez trouvées utiles . Jusque-là, joyeux essaim ...
Avez-vous aimé la méthode personnalisée Fishy __repr__
?
J'ai déjà créé mon propre poisson personnalisé basé sur la première réponse avant votre réponse. Désolé, mais votre réponse me donne un autre aperçu du nouveau code, merci
Parce que l'aliasing; la ligne
fish [i] = fish_value
est une mauvaise pratique,fish_value
est écrasée. Mais vraiment, vous pouvez éviter la boucle avec une compréhension de dict. Quoi qu'il en soit, une meilleure pratique de codage consiste à déclarer votre propre classeFish
avec des membres weight, visual, step.@smci, d'accord, il vaut donc mieux créer une classe ou un objet pour saisir la valeur de chaque boucle, merci pour vos conseils