Früher heute habe ich die Frage "Raise error if python dict comprehension overwrites a key" gelesen und beschlossen, meine Hand auf eine Antwort zu versuchen. Die Methode, die mir natürlich in den Sinn kam, war die Unterklasse dict
dafür. Ich blieb jedoch bei meiner Antwort hängen, und jetzt bin ich besessen davon, das für mich selbst zu erarbeiten.Überschreiben dict.update() -Methode in der Unterklasse, um das Überschreiben von Diktatschlüsseln zu verhindern
Hinweise:
- Nein - ich habe nicht als Antwort auf diese Frage in der Antwort auf Drehung in der anderen Frage.
- Dies ist eine rein intellektuelle Übung für mich an dieser Stelle. Praktisch würde ich fast sicher ein oder ein normales Wörterbuch verwenden, wo immer ich eine Anforderung für so etwas habe.
Meine (nicht ganz funktioniert) Lösung:
class DuplicateKeyError(KeyError):
pass
class UniqueKeyDict(dict):
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
def __setitem__(self, key, value):
if key in self: # Validate key doesn't already exist.
raise DuplicateKeyError('Key \'{}\' already exists with value \'{}\'.'.format(key, self[key]))
super().__setitem__(key, value)
def update(self, *args, **kwargs):
if args:
if len(args) > 1:
raise TypeError('Update expected at most 1 arg. Got {}.'.format(len(args)))
else:
try:
for k, v in args[0]:
self.__setitem__(k, v)
except ValueError:
pass
for k in kwargs:
self.__setitem__(k, kwargs[k])
Meine Tests und die erwarteten Ergebnisse
>>> ukd = UniqueKeyDict((k, int(v)) for k, v in ('a1', 'b2', 'c3', 'd4')) # Should succeed.
>>> ukd['e'] = 5 # Should succeed.
>>> print(ukd)
{'a': 1, 'b': 2, 'c': 3, d: 4, 'e': 5}
>>> ukd['a'] = 5 # Should fail.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __setitem__
__main__.DuplicateKeyError: Key 'a' already exists with value '1'.
>>> ukd.update({'a': 5}) # Should fail.
>>> ukd = UniqueKeyDict((k, v) for k, v in ('a1', 'b2', 'c3', 'd4', 'a5')) # Should fail.
>>>
Ich bin sicher, dass das Problem in meinem update()
Methode ist, aber ich bin nicht in der Lage zu bestimmen, was ich gerade falsch mache.
Unten ist die Originalversion meiner update()
Methode. Diese Version schlägt wie erwartet bei Duplikaten beim Aufruf von my_dict.update({k: v})
für ein Schlüssel/Wert-Paar bereits im dict fehl, scheitert jedoch nicht, wenn ein Duplikatschlüssel beim Erstellen des ursprünglichen dict eingefügt wird, da die Konvertierung der Argumente in dict
zu einem Fehler führt Verhalten für ein Wörterbuch, dh Überschreiben des doppelten Schlüssels.
def update(self, *args, **kwargs):
for k, v in dict(*args, **kwargs).items():
self.__setitem__(k, v)
Wenn höchstens ein Positions Argument erlaubt ist, verwenden Sie 'Update (self, arg = None, ** kwargs)' statt Erlauben einer beliebigen Anzahl von Argumenten. – chepner
O/t, sollte aber nicht 'DuplicateKeyError' Unterklasse' KeyError'? – jonrsharpe
@jonrsharpe - Ich dachte vor kurzem darüber nach und werde das Update machen. –