2009-06-09 6 views
4

ich die folgende Liste Verständnis mit:Caching Werte in Python Listenkomprehensionen

resources = [obj.get("file") for obj in iterator if obj.get("file") != None] 

Gibt es eine Möglichkeit, den Wert von obj.get("file") auf „Cache“, wenn es in der if-Anweisung überprüft ist, so dass es nicht der Fall ist muss wieder auf obj get aufrufen, wenn es die Rückgabeliste generiert?

Antwort

6

Wenn Sie mit der Liste/Iterator Comprehensions statt bleiben wollen filter verwenden Sie können einfach verwenden:

resources = [file_obj 
      for file_obj in (obj.get("file") for obj in iterator) 
      if file_obj is not None] 
+0

Danke, das ist die allgemeine Lösung, nach der ich gesucht habe. – Kai

9
resources = filter(None, (obj.get("file") for obj in iterator)) 

finden Sie in der Dokumentation für filter, wie Sie Ihre eigene Auswertungsfunktion zur Verfügung zu stellen. Übergeben None für die Funktion (wie oben) filtert alle Werte, die nicht wahr sind.

Wenn obj.get() ein Objekt zurückgibt, das eine seltsame __nonzero__ Methode hat, dann müssen Sie lambda obj: obj != None übergeben, um genau das gleiche Ergebnis wie Ihr ursprünglicher Code zu erhalten.

+0

„ein Objekt, das eine seltsame __nonzero__ hat“ - wie ein int oder ein str. –

1

versuchen, etwas wie folgt aus:

resources = filter(lambda x: x is not None, [obj.get("file") for ob jin iterator]) 
+0

Sie brauchen die Lambda-Funktion in Ihrem Filter nicht. Bei der Übergabe von None wird standardmäßig die Identity-Funktion verwendet (dh jedes Objekt, das als false ausgewertet wird, wird herausgefiltert). http://docs.python.org/library/functions.html#filter – tgray

+0

Auf den zweiten Gedanken, möchten Sie vielleicht das Lambda, wenn Sie andere "False" Elemente in Ihrem iterable (d. h. 0) haben. – tgray

+0

Hmm. auch wenn ich es nicht brauche, mag ich die ausdrücklichkeit des lambda. – SingleNegationElimination

1

Erstellen Sie eine temporäre dict Werte zu halten. Erstellen Sie dann eine Funktion, die diese dict als Cache verwendet, und verwenden Sie diese Funktion in der Liste Verständnis, etwa so:

obj_cache = {} 

def cache_get (target, key): 
    if (target, key) not in obj_cache: obj_cache[(target, key)] = target.get(key) 
    return obj_cache[(target, key)] 

resources = [cache_get(obj, "file") for obj in iterator if cache_get(obj, "file") != None] 

Auch Sie wahrscheinlich bereits wissen (und wenn ja, ignorieren Sie bitte diese Antwort), aber wenn obj.get ("file") einen Datenbankaufruf macht, eine Datei öffnet, eine Anfrage über ein Netzwerk macht oder etwas anderes, was möglicherweise teuer ist, tut, ist es wahrscheinlich harmlos, es zweimal pro Iteration anstelle von einmal aufzurufen Fügen Sie nur O (n) zu Ihren Kosten hinzu.