2016-08-07 9 views
10

Die folgende Sortiermethode funktioniert einwandfrei.Stellen Sie einen Teil einer Lambda-Funktion im Voraus ein, um wiederholten Code zu vermeiden

def sort_view_items(self): 

    cs = self.settings.case_sensitive 

    if self.settings.sort_by_file_name: 
     sk = lambda vi: (vi.name if cs else vi.name.lower(), vi.group, vi.tab) 

    elif self.settings.sort_by_folder: 
     sk = lambda vi: (vi.folder, vi.name if cs else vi.name.lower()) 

    elif self.settings.sort_by_syntax: 
     sk = lambda vi: (vi.syntax, vi.name if cs else vi.name.lower()) 

    elif self.settings.sort_by_indexes: 
     sk = lambda vi: (vi.group, vi.tab) 

    self.view_items.sort(key = sk) 

Jedoch ist der Groß- und Kleinschreibung entsprechende Abschnitt des Lambda vi.name if cs else vi.name.lower() 3 Mal verwendet wird, das Gen wiederholt meines Code irks.

Aus Interesse, kann der Fallaspekt im Voraus irgendwie eingestellt werden, aber ohne dauernde Änderungen am name Attribut oder so in einer temporären Kopie der view_items Liste vorzunehmen?

Zum Beispiel habe ich versucht, mit einem Lambda in einem Lambda, die ich nicht dachte, würde funktionieren und, ratet mal, was es nicht. Obwohl die Syntax unerwartet akzeptiert wurde (keine Ausnahmen), führte sie nicht dazu, dass tatsächlich eine Sortierung durchgeführt wurde.

def sort_view_items(self): 

    cs = self.settings.case_sensitive 

    name_lambda = lambda vi: vi.name if cs else vi.name.lower() 

    if self.settings.sort_by_file_name: 
     sk = lambda vi: (name_lambda, vi.group, vi.tab) 

    ... 
+4

Beachten Sie, dass das Definieren eines "Lambda" und das Zuweisen eines Namens wie diesem den gesamten Zweck von "Lambda" -Funktionen ablehnt und speziell in PEP-8 verwarnt wird. – TigerhawkT3

+0

@ TigerhawkT3 Beziehen Sie sich auf meinen "Lambda in einem Lambda" -Code oder auf das ganze 'sk = Lambda vi: (vi.name wenn cs else vi.name.lower(), vi.group, vi.tab)' code ? – mattst

+2

Es ist ein wenig effizienter, Ihre Schlüsselfunktionen außerhalb von 'sort_view_items' zu definieren. Wenn Sie Funktionen innerhalb einer anderen Funktion definieren, werden diese inneren Funktionen jedes Mal neu kompiliert, wenn Sie die äußere Funktion aufrufen. –

Antwort

5

Sie müssen tatsächlich name_lambda nennen:

sk = lambda vi: (name_lambda(vi), vi.group, vi.tab) 

In Ihrem Snippet wird name_lambda definiert richtig, aber es wird nie aufgerufen werden.

+0

Funktioniert super danke. – mattst

1

Da Sie es in 3 von 4 Bedingungen verwenden möchten, ist der beste Weg, um diese Wiederholung zu verweigern, die Berechnung des Namens an der Spitze Ihrer if Bedingungen. Sie können auch ein def Schlüsselwort verwenden, um Ihre key Funktion ordnungsgemäß zu erstellen, und den entsprechenden Wert zurückgeben, anstatt jedesmal eine Funktion zu definieren. In diesem Fall können Sie die vi an übergeben und die name die oberste Ebene dieser Funktion berechnen.

def sort_view_items(self): 

    def key_func(vi): 
     name = vi.name if self.settings.case_sensitive else vi.name.lower() 
     if self.settings.sort_by_file_name: 
      return name(vi), vi.group, vi.tab 

     elif self.settings.sort_by_folder: 
      return vi.folder,name(vi) 

     elif self.settings.sort_by_syntax: 
      return vi.syntax, name(vi) 

     elif self.settings.sort_by_indexes: 
      return vi.group, vi.tab 

    self.view_items.sort(key=key_func) 
+0

Das löst eine Ausnahme aus: 'NameError: globaler Name 'vi' ist nicht definiert ' – mattst

+0

@mattst Ja, das ist, weil Sie' vi' in Ihrem Funktionsnamensraum nicht haben, lassen Sie mich aktualisieren! – Kasramvd

+2

Auch das ist weniger effizient, da es all diese 'if' /' elif' Tests für _every_ Schlüssel durchführen muss. –

5

Dies erfordert, dass Sie eine neue Eigenschaft hinzufügen „lower_name“, um Ihre Klasse, aber diese Änderung können Sie stark den Rest des Codes vereinfachen.

+2

Sie sollten Ihren Namen (in der ersten Zeile von sort_view_items) 'name_field' nennen, um mit dem Rest des Codes konsistent zu sein. Ansonsten, große Verwendung von Attrgetter. Und _please_ benutzen '.casefold' für die Falzfaltung anstelle von' .lower' (wenn Python neu genug ist). – Veky

+0

Danke für die Fehlerbehebung, und einen guten Vorschlag für die Verwendung von 'casefold', falls verfügbar. – chepner

Verwandte Themen