Skip to content

Verwendung eines Schlüsselparameters in Python (sorted, max, etc.)

Python

In Python können Sie in den eingebauten Funktionen sorted(), max(), min() usw. eine Funktion oder einen Aufruf für den Schlüsselparameter angeben.

Dieser Artikel hat folgenden Inhalt.

  • Geben Sie eine integrierte Funktion für den Schlüsselparameter an
  • Geben Sie einen Lambda-Ausdruck oder Ihre eigene Funktion für den Schlüsselparameter an
  • Geben Sie operator.itemgetter() für den Schlüsselparameter an
  • Geben Sie operator.attrgetter() für den Schlüsselparameter an
  • Geben Sie operator.methodcaller() für den Schlüsselparameter an
  • Geschwindigkeitsvergleich zwischen Lambda-Ausdruck und operator.itemgetter().

Siehe auch den following Artikel für Beispiele zur Verwendung des Schlüsselparameters.

Geben Sie eine integrierte Funktion für den Schlüsselparameter an

Ein einfaches Beispiel für die Verwendung des Schlüsselparameters ist die Angabe einer integrierten Funktion.

Standardmäßig werden in sorted() die Elemente der Liste so sortiert und sortiert, wie sie sind.

l = [1, -3, 2]

print(sorted(l))
# [-3, 1, 2]

Wenn für den Schlüsselparameter abs() angegeben IST, das einen absoluten Wert zurückgibt, werden sterben Elemente nach dem absoluten Wert jedes Elements sortiert.

Beachten Sie, dass die Klammern () unnötig sind, WENN Eine Funktion oder Ein anderer Aufruf als Argument angegeben WIRD.

print(sorted(l, key=abs))
# [1, 2, -3]

Die in der Tonart angegebene Funktion wird nur beim Vergleich verwendet, und die Elemente im Ergebnis bleiben gleich. If SIE Eine Funktion Auf Ein Element Kopieren Und Es Konvertieren Möchten, Verwenden SIE Listenverständnisse.

l_abs = [abs(i) for i in l]
print(l_abs)
# [1, 3, 2]

print(sorted(l_abs))
# [1, 2, 3]

Dasselbe gilt für die Methode sort() von Listen.

l.sort(key=abs)
print(l)
# [1, 2, -3]

Sie können den Schlüsselparameter auch in max() und min() angeben.

l = [1, -3, 2]

print(max(l))
# 2

print(max(l, key=abs))
# -3

print(min(l))
# -3

print(min(l, key=abs))
# 1

Beachten Sie, dass key ein reiner Schlüsselwortparameter ist und daher immer wie key=xxx angegeben werden muss.

Die folgenden Beispiele verwenden sorted(), aber die Verwendung des Schlüsselparameters ist für sort(), max(), min() usw. gleich.

Ein weiteres Beispiel ist der Fall einer Liste von Zeichenfolgen. Standardmäßig IST die Liste alphabetisch sortiert, sie kann jedoch nach der Anzahl der Zeichen sortiert werden, indem len() als Schlüsselparameter angegeben WIRD.

l_str = ['bbb', 'c', 'aa']

print(sorted(l_str))
# ['aa', 'bbb', 'c']

print(sorted(l_str, key=len))
# ['c', 'aa', 'bbb']

Geben Sie einen Lambda-Ausdruck oder Ihre eigene Funktion für den Schlüsselparameter an

SIE können nicht nur eingebaute Funktionen angeben, sondern auch Lambda-Ausdrücke oder Ihre eigenen Funktionen, die mit def für den Schlüsselparameter definiert sind.

Verwenden Sie als Beispiel eine zweidimensionale Liste (Liste von Listen).

Beim Listenvergleich wird das erste Element zuerst erhoben.

l_2d = [[2, 10], [1, -30], [-3, 20]]

print(sorted(l_2d))
# [[-3, 20], [1, -30], [2, 10]]

Durch die Angabe von max() für das Schlüsselargument werden Listen nach ihren Maximalwerten sortiert.

print(sorted(l_2d, key=max))
# [[1, -30], [2, 10], [-3, 20]]

Wenn Sie nach dem maximalen Wert jeder Liste sortieren möchten, verwenden Sie einen Lambda-Ausdruck.

print(sorted(l_2d, key=lambda x: max([abs(i) for i in x])))
# [[2, 10], [-3, 20], [1, -30]]

Beachten Sie, dass Sie sich keine Sorgen machen müssen, wenn die Anzahl der Elemente in der Liste klein ist, aber Sie können möglicherweise die Speichernutzung reduzieren, indem Sie einen Generatorausdruck für max() verwenden.

print(sorted(l_2d, key=lambda x: max(abs(i) for i in x)))
# [[2, 10], [-3, 20], [1, -30]]

Sie können eine Funktion mit def anstelle eines Lambda-Ausdrucks definieren und für den Schlüssel angeben.

def max_abs(x):
    return max(abs(i) for i in x)

print(sorted(l_2d, key=max_abs))
# [[2, 10], [-3, 20], [1, -30]]

Geben Sie operator.itemgetter() für den Schlüsselparameter an

itemgetter() im Standardbibliotheksoperator gibt ein aufrufbares Objekt zurück, das ein Listenelement oder einen Wörterbuchwert abruft.

Mit operator.itegetter() sortieren Sie eine zweidimensionale Liste nach dem Wert einer beliebigen Position (Index).

import operator

l_2d = [[2, 10], [1, -30], [-3, 20]]

print(sorted(l_2d, key=operator.itemgetter(1)))
# [[1, -30], [2, 10], [-3, 20]]

Da operator.itemgetter(xxx) ein aufrufbares Element zurückgibt, geben Sie es als key=operator.itemgetter(xxx) an.

f = operator.itemgetter(1)
print(f([2, 10]))
# 10

print(operator.itemgetter(1)([2, 10]))
# 10

Sie können dasselbe mit einem Lambda-Ausdruck tun.

print(sorted(l_2d, key=lambda x: x[1]))
# [[1, -30], [2, 10], [-3, 20]]

operator.itemgetter() ist schneller als der Lambda-Ausdruck.

Das Ergebnis eines einfachen Vergleichs der Verarbeitungsgeschwindigkeit zwischen operator.itemgetter() und operator.itemgetter() WIRD am Ende beschrieben.

operator.itemgetter() kann auch für Wörterbuchwörter verwendet werden.

Als Beispiel wird eine Liste von Wörterbüchern mit einem Schlüssel verwendet. Wörterbücher können nicht miteinander erfasst werden, daher WIRD standardmäßig ein Fehler ausgelöst, aber operator.itemgetter() kann used Werden, um die Liste basierend auf dem Wert des angegebenen Schlüssels zu sortieren.

l_dict = [{'k1': 2, 'k2': 10}, {'k1': 1}, {'k1': 3}]

# print(sorted(l_dict))
# TypeError: '<' not supported between instances of 'dict' and 'dict'

print(sorted(l_dict, key=operator.itemgetter('k1')))
# [{'k1': 1}, {'k1': 2, 'k2': 10}, {'k1': 3}]

Beachten Sie, dass ein Fehler ausgelöst WIRD, WENN EIN Wörterbuch OHNE DEN ANGEGEBENEN SCHLÜSSEL ENTHALTEN IST.

# print(sorted(l_dict, key=operator.itemgetter('k2')))
# KeyError: 'k2'

Sie können dasselbe mit einem Lambda-Ausdruck tun.

print(sorted(l_dict, key=lambda x: x['k1']))
# [{'k1': 1}, {'k1': 2, 'k2': 10}, {'k1': 3}]

Wenn das Wörterbuch nicht über den angegebenen Schlüssel verfügt, können Sie ihn mit der Methode get() durch einen beliebigen Wert ersetzen. Siehe folgenden Artikel.

Wenn mehrere Argumente für operator.itemgetter() angegeben werden, WIRD ein Tupel zurückgegeben, das. Das Ergebnis von jedem enthält.

l_dict = [{'k1': 2, 'k2': 'ccc'}, {'k1': 1, 'k2': 'ccc'}, {'k1': 2, 'k2': 'aaa'}]

print(operator.itemgetter('k1', 'k2')(l_dict[0]))
# (2, 'ccc')

Tupel werden auch wie Listen in der Reihenfolge vom ersten Element erfasst.

print(sorted(l_dict, key=operator.itemgetter('k1')))
# [{'k1': 1, 'k2': 'ccc'}, {'k1': 2, 'k2': 'ccc'}, {'k1': 2, 'k2': 'aaa'}]

print(sorted(l_dict, key=operator.itemgetter('k1', 'k2')))
# [{'k1': 1, 'k2': 'ccc'}, {'k1': 2, 'k2': 'aaa'}, {'k1': 2, 'k2': 'ccc'}]

print(sorted(l_dict, key=operator.itemgetter('k2', 'k1')))
# [{'k1': 2, 'k2': 'aaa'}, {'k1': 1, 'k2': 'ccc'}, {'k1': 2, 'k2': 'ccc'}]

Sie können dasselbe auch mit einem Lambda-Ausdruck tun.

print(sorted(l_dict, key=lambda x: (x['k1'], x['k2'])))
# [{'k1': 1, 'k2': 'ccc'}, {'k1': 2, 'k2': 'aaa'}, {'k1': 2, 'k2': 'ccc'}]

Geben Sie operator.attrgetter() für den Schlüsselparameter an

operator.attrgetter() gibt ein aufrufbares Objekt zurück, das ein Attribut abruft.

Verwenden Sie als Beispiel eine Liste von datetime.date-Objekten. Sie können Tag, Monat und Jahr mit den Attributen Tag, Monat und Jahr von datetime.date abrufen.

import datetime

l_dt = [datetime.date(2003, 2, 10), datetime.date(2001, 3, 20), datetime.date(2002, 1, 30)]

print(l_dt[0])
# 2003-02-10

print(l_dt[0].day)
# 10

f = operator.attrgetter('day')
print(f(l_dt[0]))
# 10

Standardmäßig sind sie nach Datum sortiert, aber sie können mit operator.attrgetter() nach jedem beliebigen Attribut sortieren.

print(sorted(l_dt))
# [datetime.date(2001, 3, 20), datetime.date(2002, 1, 30), datetime.date(2003, 2, 10)]

print(sorted(l_dt, key=operator.attrgetter('day')))
# [datetime.date(2003, 2, 10), datetime.date(2001, 3, 20), datetime.date(2002, 1, 30)]

Obwohl operator.attrgetter() schneller ist, kann dies auch mit einem Lambda-Ausdruck erfolgen.

print(sorted(l_dt, key=lambda x: x.day))
# [datetime.date(2003, 2, 10), datetime.date(2001, 3, 20), datetime.date(2002, 1, 30)]

Geben Sie operator.methodcaller() für den Schlüsselparameter an

operator.methodcaller() gibt ein aufrufbares Objekt zurück, das eine Methode aufruft.

Verwenden Sie als Beispiel die Methode find(), die die Position einer bestimmten Zeichenfolge zurückgibt.

l_str = ['0_xxxxA', '1_Axxxx', '2_xxAxx']

print(l_str[0])
# 0_xxxxA

print(l_str[0].find('A'))
# 6

f = operator.methodcaller('find', 'A')
print(f(l_str[0]))
# 6

Standardmäßig ist es alphabetisch sortiert, aber Sie können mit operator.methodcaller() nach den Ergebnissen jeder Methode sortieren.

print(sorted(l_str))
# ['0_xxxxA', '1_Axxxx', '2_xxAxx']

print(sorted(l_str, key=operator.methodcaller('find', 'A')))
# ['1_Axxxx', '2_xxAxx', '0_xxxxA']

Obwohl operator.attrgetter() schneller ist, kann dies auch mit einem Lambda-Ausdruck erfolgen.

print(sorted(l_str, key=lambda x: x.find('A')))
# ['1_Axxxx', '2_xxAxx', '0_xxxxA']

Geschwindigkeitsvergleich zwischen Lambda-Ausdruck und operator.itemgetter().

Dieser Abschnitt zeigt die Ergebnisse eines einfachen Geschwindigkeitsvergleichs zwischen Lambda-Ausdrücken und operator.itegetter().

Verwenden Sie als Beispiel eine Liste von Wörterbüchern mit einem Schlüssel (10000 Elemente).

import operator

l = [{'k1': i} for i in range(10000)]

print(len(l))
# 10000

print(l[:5])
# [{'k1': 0}, {'k1': 1}, {'k1': 2}, {'k1': 3}, {'k1': 4}]

print(l[-5:])
# [{'k1': 9995}, {'k1': 9996}, {'k1': 9997}, {'k1': 9998}, {'k1': 9999}]

Beachten Sie, dass der folgende Code den magischen Jupyter Notebook-Befehl %%timeit used und nicht funktioniert, wenn er als Python-Skript ausgeführt WIRD.

%%timeit
sorted(l, key=lambda x: x['k1'])
# 1.09 ms ± 35 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
sorted(l, key=operator.itemgetter('k1'))
# 716 µs ± 28.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
sorted(l, key=lambda x: x['k1'], reverse=True)
# 1.11 ms ± 41.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
sorted(l, key=operator.itemgetter('k1'), reverse=True)
# 768 µs ± 58.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
max(l, key=lambda x: x['k1'])
# 1.33 ms ± 130 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
max(l, key=operator.itemgetter('k1'))
# 813 µs ± 54.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
min(l, key=lambda x: x['k1'])
# 1.27 ms ± 69.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
min(l, key=operator.itemgetter('k1'))
# 824 µs ± 83.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

operator.itegetter() ist schneller als Lambda-Ausdrücke für alle Funktionen sorted(), max() und min().

Natürlich können die Ergebnisse je nach Umgebung und Bedingungen (Anzahl der Elemente etc.) variieren.