Wie entferne ich einen Schlüssel aus einem Python-Wörterbuch?

1767

Beim Löschen eines Schlüssels aus einem Wörterbuch verwende ich:

if 'key' in my_dict:
    del my_dict['key']

Gibt es eine einzeilige Möglichkeit, dies zu tun?

Tony
quelle
24
Benchmark-Skript für die verschiedenen Methoden, die in den Antworten auf diese Frage vorgeschlagen wurden: gist.github.com/zigg/6280653
zigg

Antworten:

2840

Verwenden Sie die Zwei-Argumente-Form von dict.pop(): Um einen Schlüssel zu löschen, unabhängig davon, ob er sich im Wörterbuch befindet :

my_dict.pop('key', None)

Dies wird zurückgegeben, my_dict[key]wenn keyes im Wörterbuch vorhanden ist, und Noneansonsten. Wenn der zweite Parameter nicht angegeben ist (dh my_dict.pop('key')) und keynicht existiert, KeyErrorwird a ausgelöst.

Sie können auch einen Schlüssel löschen, dessen Existenz garantiert ist

del my_dict['key']

Dies löst ein aus, KeyErrorwenn sich der Schlüssel nicht im Wörterbuch befindet.

Sven Marnach
quelle
152
Manchmal ein Vorteil der Verwendung von pop()over del: Es wird der Wert für diesen Schlüssel zurückgegeben. Auf diese Weise können Sie einen Eintrag aus einem Diktat in einer Codezeile abrufen und löschen.
Kratenko
7
In der Frage ist es nicht erforderlich, den Wert zu behalten. Dies würde nur unnötige Komplexität hinzufügen. Die Antwort von @zigg (unten) ist viel besser.
Salvatore Cosentino
10
@SalvatoreCosentino Ich kann Ihrem Argument nicht folgen. Wie ist der Code in dieser Antwort komplexer als der Code in der anderen Antwort?
Sven Marnach
33
@SalvatoreCosentino Nein, das Ignorieren des Rückgabewerts einer Funktion ist überhaupt nicht ineffizient. Im Gegenteil - diese Lösung ist viel schneller als die try/ except-Lösung, wenn der Schlüssel nicht vorhanden ist. Möglicherweise ist das eine oder andere leichter zu lesen, was in Ordnung ist. Beide sind idiomatische Python, wählen Sie also, was Sie bevorzugen. Die Behauptung, diese Antwort sei komplexer oder ineffizienter, macht einfach keinen Sinn.
Sven Marnach
5
@ user5359531 Ich verstehe nicht. Wie ist das ein Problem? Keine der Methoden in Pythons integrierten Typen gibt zurück self, daher wäre es ziemlich überraschend, wenn dies der Fall wäre.
Sven Marnach
353

Speziell zu antworten: "Gibt es eine einzeilige Möglichkeit, dies zu tun?"

if 'key' in my_dict: del my_dict['key']

... na du hast gefragt ;-)

Sie sollten jedoch bedenken, dass auf diese Weise ein Objekt aus einem zu löschen dictist nicht atomar -es ist möglich , dass 'key'sein in kann my_dictwährend der ifAussage, aber kann , bevor sie gelöscht werden , delausgeführt wird , wobei in diesem Fall delmit einem fehlschlagen wird KeyError. Vor diesem Hintergrund wäre es am sichersten zu jeder Nutzungdict.pop oder etwas entlang der Linien von

try:
    del my_dict['key']
except KeyError:
    pass

Das ist natürlich definitiv kein Einzeiler.

Zickzack
quelle
27
Ja, popist definitiv prägnanter, obwohl es einen entscheidenden Vorteil gibt, es so zu machen: Es ist sofort klar, was es tut.
Zigg
4
Die try/exceptAussage ist teurer. Das Auslösen einer Ausnahme ist langsam.
Chris Barker
16
@ ChrisBarker Ich habe festgestellt, dass der Schlüssel, wenn er existiert, trygeringfügig schneller ist, wenn er nicht vorhanden ist, tryist er in der Tat viel langsamer. popist ziemlich konsistent, aber langsamer als alle anderen, jedoch trymit einem nicht vorhandenen Schlüssel. Siehe gist.github.com/zigg/6280653 . Letztendlich hängt es davon ab, wie oft Sie erwarten, dass der Schlüssel tatsächlich im Wörterbuch enthalten ist, und ob Sie Atomizität benötigen oder nicht - und natürlich, ob Sie sich auf vorzeitige Optimierung
einlassen
9
Ich glaube, der Wert der Klarheit sollte nicht übersehen werden. +1 dafür.
Juan Carlos Coto
2
In Bezug auf die Kosten für den Versuch / außer können Sie auch gehen if 'key' in mydict: #then del.... Ich musste einen Schlüssel / Wert aus einem Diktat herausziehen, um richtig zu analysieren. Pop war keine perfekte Lösung.
Marc
153

Ich habe einige Zeit gebraucht, um herauszufinden, was genau my_dict.pop("key", None)passiert. Also werde ich dies als Antwort hinzufügen, um anderen Zeit beim Googeln zu sparen:

pop(key[, default])

Wenn sich der Schlüssel im Wörterbuch befindet, entfernen Sie ihn und geben Sie seinen Wert zurück. Andernfalls geben Sie den Standardwert zurück . Wenn die Standardeinstellung nicht angegeben ist und sich der Schlüssel nicht im Wörterbuch befindet, KeyErrorwird a ausgelöst.

Dokumentation

Akavall
quelle
15
Geben Sie einfach help (dict.pop) in den Python-Interpreter ein.
David Mulder
13
help () und dir () können deine Freunde sein, wenn du wissen musst, was etwas tut.
David Mulder
3
oder dict.pop?in IPython.
Erik Kaplun
51

del my_dict[key]ist etwas schneller als my_dict.pop(key)zum Entfernen eines Schlüssels aus einem Wörterbuch, wenn der Schlüssel vorhanden ist

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

Aber wenn der Schlüssel nicht existiert, if key in my_dict: del my_dict[key]ist etwas schneller als my_dict.pop(key, None). Beide sind mindestens dreimal schneller als delin einer try/ except-Anweisung:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133
Peter Smit
quelle
1
Das Messen des Timings einer so schnellen Operation ist ziemlich dumm. Ihr Code wird wahrscheinlich nicht viel schneller, weil Sie a popin a geändert haben del. Das Erstellen des Wörterbuchs wird das Löschen von Inhalten vollständig in den Schatten stellen.
Boris
1
@ Boris - Dies ist nützlich als allgemeine Übung.
Gänseblümchen
1
@daisy Was ich sage ist, dass Sie die am besten lesbare Syntax wählen sollten, nicht die Operation, die 300 Nanosekunden schneller ist (das ist buchstäblich der Unterschied zwischen delund popvom ersten Satz von Timings oben)
Boris
Auch diese Operationen sind so schnell, dass diese Timings nicht zuverlässig sind.
Boris
46

Wenn Sie viele Schlüssel in einer Codezeile aus einem Wörterbuch entfernen müssen, ist die Verwendung von map () meiner Meinung nach recht prägnant und pythonisch lesbar:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

Und wenn Sie Fehler abfangen müssen, bei denen Sie einen Wert einfügen, der nicht im Wörterbuch enthalten ist, verwenden Sie Lambda in map () wie folgt:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

oder in python3müssen Sie stattdessen ein Listenverständnis verwenden:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

Es klappt. Und 'e' hat keinen Fehler verursacht, obwohl myDict keinen 'e'-Schlüssel hatte.

Marc Maxmeister
quelle
42
Dies funktioniert in Python 3 nicht, da mapFreunde jetzt faul sind und Iteratoren zurückgeben. Die Anwendung mapbei Nebenwirkungen wird im Allgemeinen als schlechte Praxis angesehen. Eine Standardschleife for ... inwäre besser. Weitere Informationen finden Sie unter Ansichten und Iteratoren anstelle von Listen .
Greg Krimer
5
Unabhängig von Geschmack und Übungsstil sollte das Listenverständnis in Py3 weiterhin funktionieren [myDict.pop(i, None) for i in ['a', 'c']], da es eine allgemeine Alternative zu map(und filter) darstellt.
Michael Ekoka
@MichaelEkoka Sie sollten keine Listenverständnisse für ihre Nebenwirkungen verwenden, verwenden Sie eine reguläre for ... inSchleife.
Boris
@ Boris Du hast wahrscheinlich recht. Meine Antwort bezieht sich speziell auf die Verwendung map(), die häufig wegen ihrer Nebenwirkungen verwendet wird. Die empfohlene Alternative in Python ist das Listenverständnis, das meiner Meinung nach als Einzeiler noch gut lesbar und kognitiv leicht ist (siehe Frage). Beide Konstrukte werden nur wegen ihrer Nebenwirkungen verwendet und führen tatsächlich zu einer nutzlosen Liste, die ineffizient sein kann. Ab Python3 ist mir keine integrierte Funktion bekannt, die einen Generatorausdruck sicher und elegant durchlaufen kann, ohne ein kostspieliges Nebenprodukt, z loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka
Ich bin amüsiert, dass meine bisher am besten bewertete Antwort einige Hacks enthält, die ich niemals verwenden würde. Das Listenverständnis (Option 3) ist meiner Meinung nach der am wenigsten schlechte Ansatz. Verwenden Sie diesen.
Marc Maxmeister
20

Sie können ein Wörterbuchverständnis verwenden , um ein neues Wörterbuch mit entferntem Schlüssel zu erstellen:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

Sie können nach Bedingungen löschen. Kein Fehler, wenn keynicht vorhanden.

Shameem
quelle
13

Verwenden des Schlüsselworts "del":

del dict[key]
Sarthak Gupta
quelle
7

Wir können einen Schlüssel aus einem Python-Wörterbuch durch die folgenden Ansätze löschen.

Verwenden des delSchlüsselworts; Es ist fast der gleiche Ansatz wie Sie -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

Oder

Wir können Folgendes tun:

Man sollte jedoch bedenken, dass in diesem Prozess tatsächlich kein Schlüssel aus dem Wörterbuch gelöscht wird, anstatt einen bestimmten Schlüssel aus diesem Wörterbuch auszuschließen . Außerdem stellte ich fest, dass ein Wörterbuch zurückgegeben wurde, das nicht wie das gleiche bestellt wurde myDict.

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

Wenn wir es in der Shell ausführen, wird es ungefähr so ​​ausgeführt {'five': 500, 'four': 400, 'three': 300, 'two': 200}- beachten Sie, dass es nicht die gleiche Reihenfolge wie hat myDict. Wenn wir erneut versuchen zu drucken myDict, können wir alle Schlüssel sehen, einschließlich derer, die wir durch diesen Ansatz aus dem Wörterbuch ausgeschlossen haben. Wir können jedoch ein neues Wörterbuch erstellen, indem wir einer Variablen die folgende Anweisung zuweisen:

var = {key:value for key, value in myDict.items() if key != 'one'}

Wenn wir nun versuchen, es zu drucken, folgt es der übergeordneten Reihenfolge:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

Oder

Mit der pop()Methode.

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

Der Unterschied zwischen delund popbesteht darin, dass pop()wir mithilfe der Methode den Wert des Schlüssels bei Bedarf tatsächlich speichern können , wie folgt:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

Gabel diesen Kern für die Zukunft, wenn Sie diesen Kommentar hilfreich.

iNet
quelle
1
if myDict.get('one')Überprüfen Sie nicht , ob ein Schlüssel vorhanden ist! Es schlägt fehl, wenn myDict ['one'] einen Falsey-Wert hat. Außerdem haben Diktate keine inhärente Reihenfolge, daher ist es nicht sinnvoll, sie zu erwähnen.
Rob
@ Rob-Dikte werden nach Einfügereihenfolge ab CPython 3.6 und alle anderen Python-Implementierungen ab 3.7 sortiert.
Boris
4

Sie können die Ausnahmebehandlung verwenden, wenn Sie sehr ausführlich sein möchten:

try: 
    del dict[key]

except KeyError: pass

Dies ist jedoch langsamer als die pop()Methode, wenn der Schlüssel nicht vorhanden ist.

my_dict.pop('key', None)

Für ein paar Tasten spielt es keine Rolle, aber wenn Sie dies wiederholt tun, ist die letztere Methode die bessere Wahl.

Der schnellste Ansatz ist folgender:

if 'key' in dict: 
    del myDict['key']

Diese Methode ist jedoch gefährlich, da a entfernt wird, wenn 'key'sie zwischen den beiden Zeilen entfernt KeyErrorwird.

Alec Alameddine
quelle
1

Ich bevorzuge die unveränderliche Version

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}
CervEd
quelle
1

Eine andere Möglichkeit ist die Verwendung von Elementen () + Diktatverständnis

items () in Verbindung mit dem Verständnis von Diktaten können uns auch dabei helfen, die Aufgabe des Löschens von Schlüssel-Wert-Paaren zu erreichen. Es hat jedoch den Nachteil, keine Inplace-Diktiertechnik zu sein. Eigentlich ein neues Diktat, wenn es erstellt wird, mit Ausnahme des Schlüssels, den wir nicht einschließen möchten.

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

Ausgabe:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
Sai Kiran Sangam
quelle
0

Einzelfilter am Schlüssel

  • Geben Sie "key" zurück und entfernen Sie ihn aus my_dict, wenn "key" in my_dict vorhanden ist
  • return None, wenn "key" in my_dict nicht vorhanden ist

dies wird sich ändern my_dict(veränderlich)

my_dict.pop('key', None)

Mehrere Filter auf Schlüsseln

ein neues Diktat generieren (unveränderlich)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
ZenG
quelle