2017-06-28 1 views
4

Backgroud Wert von nicht vorhandenen Schlüssel erstellen mit einer Funktion:Wie automatisch

Lassen Sie uns sagen, dass ich eine Funktion haben (natürlich in der Realität, die eine komplexere Funktion wäre):

def f(x): 
    return str(x) 

wenn ich will, Werte speichern unnötige erneute Berechnung zu vermeiden, kann ich eine dict wie folgt erstellen:

my_dict = {x: f(x) for x in range(5)} 

Aber dann, wenn ich tun nicht im Voraus wissen, welche Werte ich brauche, zum Beispiel 10, my_dict[10] erzeugt offensichtlich eine KeyError.

Ein Weg, um dies könnte sein:

my_dict = {} 
def get_value(x): 
    if x not in my_dict: 
     my_dict[x] = f(x) 
    return my_dict[x] 

get_value(10) 

Frage: Dies zu defaultdict sehr ähnlich scheint: Gibt es einen Weg, um die intuitive (aber gebrochen) my_dict = defaultdict(f) Arbeit, das heißt zu machen, wenn ein Schlüssel x existiert nicht, sollte es f(x) statt f() anrufen, um den Standardwert zu erstellen?

Antwort

2

Sie Ihren eigenen dict Datentyp aufbauen können. in Ihrem Fall wird __missing__ helfen. Wenn kein Schlüssel vorhanden ist, löst die Methode __missing__ Ihre benutzerdefinierte Arbeit aus. Unten ist ein einfaches Beispiel.

from collections import UserDict 
class MyDict(UserDict): 
    def __missing__(self, key): 
     self[key] = 2*key 
     return self[key] 

if __name__ == '__main__': # test 
    a = MyDict((x, 2*x) for x in range(5)) 
    print(a) 
    # {0: 0, 1: 2, 2: 4, 3: 6, 4: 8} 
    a[5] 
    # 10 
    print(a) 
    # {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5:10} 

beachten Sie auch, dass UserDict ist ein Wrapper um Dictionary-Objekte, so dass Sie bequem die Wörterbuchdatentypen Subklassen.

Überprüfen Sie die offizielle Dokumentation.

+1

'UserDict' ist nur in Python 2 notwendig.Bei Verwendung von Python 3 ist es möglich, direkt von dict 'class MyDict (dict) zu erben:' – robru

+0

'von Sammlungsimport UserDict' funktioniert nicht für mich (entweder' Kein Modul namens collection' (statt 'collections'?) Oder 'kann den Namen UserDict' nicht importieren, aber die Verwendung von'dict' als Basis für' MyDict' funktioniert gut! – Julien

+0

den Tippfehler, 'collection' in' collections' behoben;] – Leonard2

3

Basierend auf the docs könnte der Lage sein, das Verhalten Sie wollen bekommen Subklassen defaultdict und überwiegendes __missing__:

from collections import defaultdict 
class betterdefault(defaultdict): 
    def __missing__(self, key): 
     return self.default_factory(key) 

Nun, würden Sie wollen, dass mit ein wenig mehr Logik konkretisieren, zB throw KeyError wenn self.default_factory ist keine, Zeug wie das, was sie in den Dokumenten erwähnen. Hoffe, das zeigt Ihnen in die richtige Richtung.

Hier ist ein schnelles demo

+1

Das ist ziemlich cool, aber '__missing__' gesetzt keinen Wert. Vielleicht einen Anruf zu 'self.setitem (key, self.default_factory (key))' hinzufügen? –

+1

[Erfolg!] (Https://repl.it/JFCp/1) Sehr schön, +1 –

+0

Nette Teamarbeit Jungs! Warten, um zu sehen, ob jemand mit einer einfacheren Lösung kommt, bevor er akzeptiert. – Julien