Existe-t-il un moyen de supprimer un élément d'un dictionnaire en Python?
De plus, comment puis-je supprimer un élément d'un dictionnaire pour renvoyer une copie (c'est-à-dire sans modifier l'original)?
python
dictionary
del
richzilla
la source
la source
pop
méthode modifie le dictionnaire en place . Par conséquent, il modifie la référence au dictionnaire qui a été transmise de l'appelant à la "fonction d'assistance". Ainsi, la "fonction d'assistance" n'a pas besoin de renvoyer quoi que ce soit, car la référence d'origine au dictionnaire dans l'appelant sera déjà modifiée. N'attribuez le retour dedict.pop()
à rien si vous n'en avez pas besoin. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Utilisezdeepcopy(my_dict)
si nécessaire.d.pop()
, j'ai fixé le titre pour poser la question spécifiée dans les détails.d.pop(key)
. Mais si quelque chose modifie jamais la copie superficielle, vous avez un problème bien connu avec l'aliasing . Cela aide si vous nous dites le contexte plus large. (Y a-t-il autre chose qui modifie les valeurs de dict? Essayez-vous d'itérer de manière destructive une liste?Réponses:
L'
del
instruction supprime un élément:Cependant, cela mute le dictionnaire existant de sorte que le contenu du dictionnaire change pour quiconque ayant une référence à la même instance. Pour renvoyer un nouveau dictionnaire, faites une copie du dictionnaire:
Le
dict()
constructeur fait une copie superficielle . Pour faire une copie complète, voir lecopy
module .Notez que faire une copie pour chaque dict
del
/ affectation / etc. signifie que vous passez d'un temps constant à un temps linéaire, et que vous utilisez également un espace linéaire. Pour les petits dict, ce n'est pas un problème. Mais si vous prévoyez de faire beaucoup de copies de grands dict, vous voulez probablement une structure de données différente, comme un HAMT (comme décrit dans cette réponse ).la source
dict
pendant que vous le parcourez, cela vous donnera une erreur:RuntimeError: dictionary changed size during iteration
pop
méthode qui en fait fait de même? N'est-ce pas plus pythonique? (étant la méthode de dict, pas un mot réservé spécial)?pop
mute le dictionnaire.Si vous souhaitez conserver l'original, vous pouvez simplement le copier.
la source
pop
renvoie la valeur qui a été «sautée», ce qui vous permet d'utiliser cette valeur pour une autre raison. Si ce n'est pas plus "Pythonic", je dirais que ça semble mieux, c'est sûr :). Ce n'est pas un dicton, mais cela fonctionne de la même manière pour les deux: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
peut être fourni avec une valeur par défaut qui sera retournée lorsqu'une clé est manquante dans dict. C'est bien quand vous devez retirer quelques clés mais certaines d'entre elles peuvent être manquantes;del
jetteraitKeyError
dans un tel cas.Je pense que votre solution est la meilleure façon de le faire. Mais si vous voulez une autre solution, vous pouvez créer un nouveau dictionnaire en utilisant les clés de l'ancien dictionnaire sans inclure votre clé spécifiée, comme ceci:
la source
{i:a[i] for i in a if i not in [0, 1, 2]}
si vous souhaitez supprimer plusieurs éléments.{k:v for k,v in a.items() if k != 0}
je pense.**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
L' instruction del est ce que vous recherchez. Si vous avez un dictionnaire nommé foo avec une clé appelée «bar», vous pouvez supprimer «bar» de foo comme ceci:
Notez que cela modifie de façon permanente le dictionnaire utilisé. Si vous souhaitez conserver le dictionnaire d'origine, vous devrez au préalable en créer une copie:
L'
dict
appel fait une copie superficielle. Si vous voulez une copie complète, utilisezcopy.deepcopy
.Voici une méthode que vous pouvez copier et coller, pour votre commodité:
la source
>>>
est-il souvent utilisé dans les exemples python? Oui, python-doc contient beaucoup de ces choses. Mais un tel code n'est pas pratique pour le copypaste . Je suis confus ...>>>
imite la notation d'écoute de python en mode cli>>>
. Oui, c'est du style REPL, mais parlons franchement: le seul homme avait écrit cet échantillon, et 1000 l'ont lu. Je pense que ce serait formidable d'écrire des exemples de manière à permettre une copie et une exécution faciles. Je n'aime pas retirer ces équerres à la main. Ou copier ligne par ligne .. Donc je ne comprends pas: pourquoi ces angles sont toujours là))) Peut-être que je ne sais pas quelque chose?Il y a beaucoup de bonnes réponses, mais je tiens à souligner une chose.
Vous pouvez utiliser à la fois la
dict.pop()
méthode et une instruction plus génériquedel
pour supprimer des éléments d'un dictionnaire. Ils mutent tous les deux le dictionnaire d'origine, vous devez donc en faire une copie (voir les détails ci-dessous).Et les deux lèveront un
KeyError
si la clé que vous leur fournissez n'est pas présente dans le dictionnaire:et
Vous devez vous en occuper:
en capturant l'exception:
et
en effectuant une vérification:
et
mais avec
pop()
il y a aussi un moyen beaucoup plus concis - fournissez la valeur de retour par défaut:Sauf si vous utilisez
pop()
pour obtenir la valeur d'une clé supprimée, vous pouvez fournir quoi que ce soit, non nécessaireNone
. Bien qu'il soit possible que l'utilisationdel
avecin
vérification soit légèrement plus rapide en raison du fait qu'ellepop()
est une fonction avec ses propres complications entraînant des frais généraux. Habituellement, ce n'est pas le cas, doncpop()
avec une valeur par défaut, c'est assez bon.Quant à la question principale, vous devrez faire une copie de votre dictionnaire, pour enregistrer le dictionnaire d'origine et en avoir un nouveau sans que la clé ne soit supprimée.
D'autres personnes suggèrent ici de faire une copie complète (profonde) avec
copy.deepcopy()
, ce qui pourrait être une exagération, une copie "normale" (peu profonde), en utilisantcopy.copy()
oudict.copy()
, pourrait être suffisant. Le dictionnaire conserve une référence à l'objet comme valeur pour une clé. Ainsi, lorsque vous supprimez une clé d'un dictionnaire, cette référence est supprimée, pas l'objet référencé. L'objet lui-même peut être supprimé plus tard automatiquement par le garbage collector, s'il n'y a pas d'autres références pour lui dans la mémoire. Faire une copie complète nécessite plus de calculs par rapport à une copie superficielle, donc cela diminue les performances du code en faisant la copie, en gaspillant de la mémoire et en fournissant plus de travail au GC, parfois une copie superficielle suffit.Cependant, si vous avez des objets mutables en tant que valeurs de dictionnaire et prévoyez de les modifier plus tard dans le dictionnaire renvoyé sans la clé, vous devez effectuer une copie complète.
Avec copie superficielle:
Avec copie profonde:
la source
A
dict
est la mauvaise structure de données à utiliser pour cela.Bien sûr, copier le dict et sauter à partir de la copie fonctionne, tout comme la construction d'un nouveau dict avec une compréhension, mais tout cela prend du temps - vous avez remplacé une opération à temps constant par une opération à temps linéaire. Et toutes ces copies vivantes prennent à la fois de l'espace - un espace linéaire par copie.
D'autres structures de données, comme les essais mappés de tableaux de hachage , sont conçues exactement pour ce type de cas d'utilisation: l'ajout ou la suppression d'un élément renvoie une copie en temps logarithmique, partageant la majeure partie de son stockage avec l'original . 1
Bien sûr, il y a quelques inconvénients. Les performances sont logarithmiques plutôt que constantes (bien qu'avec une grande base, généralement 32-128). Et, bien que vous puissiez rendre l'API non mutante identique à
dict
, l'API "mutante" est évidemment différente. Et, surtout, il n'y a pas de piles HAMT incluses avec Python. 2La
pyrsistent
bibliothèque est une implémentation assez solide des remplacements de dict basés sur HAMT (et divers autres types) pour Python. Il a même une API évolutive astucieuse pour porter le code de mutation existant vers du code persistant aussi facilement que possible. Mais si vous voulez être explicite sur le retour des copies plutôt que sur la mutation, vous devez simplement l'utiliser comme ceci:C'est
d3 = d1.remove('a')
exactement ce que demande la question.Si vous avez des structures de données mutables comme
dict
etlist
intégrées dans lepmap
, vous aurez toujours des problèmes d'alias - vous ne pouvez résoudre ce problème qu'en allant immuable jusqu'en bas, en incorporant lespmap
s et lespvector
s.1. Les HAMT sont également devenus populaires dans des langages comme Scala, Clojure, Haskell parce qu'ils jouent très bien avec la programmation sans verrouillage et la mémoire transactionnelle logicielle, mais aucun de ceux-ci n'est très pertinent en Python.
2. En fait, il y a un HAMT dans le stdlib, utilisé dans l'implémentation de
contextvars
. Le PEP retiré précédemment explique pourquoi. Mais c'est un détail d'implémentation caché de la bibliothèque, pas un type de collection publique.la source
Résultat:
d = {1: 2, '2': 3}
la source
Appelez simplement del d ['clé'].
Cependant, en production, c'est toujours une bonne pratique de vérifier si la «clé» existe en d.
la source
try-except
bloc. Au moins, ce sera une opération atomique;)d.pop('key', None)
-le. Mais la vraie question était d'obtenir le dictionnaire sans une clé, et non de modifier le dict. Donc les compréhensions - est un bon choix ici;)Non, il n'y a pas d'autre moyen que
Cependant, la création de copies de dictionnaires légèrement modifiés n'est souvent pas une bonne idée car elle entraînera des demandes de mémoire relativement importantes. Il est généralement préférable d'enregistrer l'ancien dictionnaire (si nécessaire), puis de le modifier.
la source
la source
cela ne fait aucune gestion des erreurs, il suppose que la clé est dans le dict, vous voudrez peut-être le vérifier d'abord et
raise
si ce n'est pas le casla source
del test_dict[key]
?Voici une approche de conception de haut niveau:
Je passe le dictionnaire et la clé que je veux dans ma fonction, valide si c'est un dictionnaire et si la clé est correcte, et si les deux existent, supprime la valeur du dictionnaire et imprime les restes.
Production:
{'B': 55, 'A': 34}
J'espère que cela pourra aider!
la source
L'extrait de code ci-dessous vous aidera certainement, j'ai ajouté des commentaires dans chaque ligne qui vous aideront à comprendre le code.
ou vous pouvez également utiliser dict.pop ()
ou la meilleure approche est
la source
Voici une autre variante utilisant la compréhension de liste:
L'approche est basée sur une réponse de ce post: moyen efficace pour supprimer des clés avec des chaînes vides d'un dict
la source
if v
pourif k is not 'a'
répondre à l'op. Mais je ne pense pas que ce soit un moyen efficace, cela supprime l'élément dans O (n) plutôt que O (log n) comme pop ou del.Le code suivant fera une copie de dict
species
et supprimera les éléments qui ne sont pas danstrans_HI
la source