Get started learning Python with DataCamp's free Intro to Python tutorial. Learn Data Science by completing interactive coding challenges and watching videos by expert instructors. Start Now!
This site is generously supported by DataCamp. DataCamp offers online interactive Python Tutorials for Data Science. Join 11 million other learners and get started learning Python for data science today!
Good news! You can save 25% off your Datacamp annual subscription with the code LEARNPYTHON23ALE25 - Click here to redeem your discount
Map, Filter, Reduce
Map, Filter und Reduce sind Paradigmen der funktionalen Programmierung. Sie ermöglichen es dem Programmierer (Ihnen), einfacheren, kürzeren Code zu schreiben, ohne sich unbedingt um komplizierte Details wie Schleifen und Verzweigungen kümmern zu müssen.
Im Wesentlichen erlauben Ihnen diese drei Funktionen, eine Funktion auf eine Anzahl von Iterablen in einem Zug anzuwenden. map
und filter
sind standardmäßig in Python eingebaut (im Modul __builtins__
) und erfordern keinen Import. reduce
muss jedoch importiert werden, da es im Modul functools
liegt. Lassen Sie uns besser verstehen, wie sie alle funktionieren, beginnend mit map
.
Map
Die map()
Funktion in Python hat die folgende Syntax:
map(func, *iterables)
Dabei ist func
die Funktion, die auf jedes Element in iterables
(so viele es auch sind) angewendet wird. Beachten Sie das Sternchen (*
) bei iterables
? Es bedeutet, dass es so viele Iterablen wie möglich geben kann, solange func
genau so viele als erforderliche Eingabeargumente hat. Bevor wir zu einem Beispiel übergehen, ist es wichtig, dass Sie Folgendes beachten:
- In Python 2 gibt die
map()
-Funktion eine Liste zurück. In Python 3 gibt die Funktion jedoch einmap object
zurück, das ein Generatorobjekt ist. Um das Ergebnis als Liste zu erhalten, kann die eingebautelist()
-Funktion auf das Mapobjekt aufgerufen werden, d.h.list(map(func, *iterables))
- Die Anzahl der Argumente für
func
muss die Anzahl der angegebeneniterables
sein.
Lassen Sie uns sehen, wie diese Regeln mit den folgenden Beispielen umgesetzt werden.
Wenn ich eine Liste (iterable
) meiner Lieblings-Haustiernamen habe, alle in Kleinbuchstaben, und sie in Großbuchstaben benötige. Traditionell würde ich in normalem Python so etwas tun:
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = []
for pet in my_pets:
pet_ = pet.upper()
uppered_pets.append(pet_)
print(uppered_pets)
Was dann ['ALFRED', 'TABITHA', 'WILLIAM', 'ARLA']
ausgeben würde.
Mit map()
-Funktionen ist es nicht nur einfacher, sondern auch viel flexibler. Ich mache einfach das:
# Python 3
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = list(map(str.upper, my_pets))
print(uppered_pets)
Was ebenfalls das gleiche Ergebnis ausgeben würde. Beachten Sie, dass nach der oben definierten map()
-Syntax func
in diesem Fall str.upper
ist und iterables
die Liste my_pets
-- nur ein Iterable. Beachten Sie auch, dass wir die str.upper
-Funktion nicht aufgerufen haben (also: str.upper()
), da die Map-Funktion dies für uns auf jedes Element in der my_pets
-Liste tut.
Was noch wichtiger zu beachten ist: Die str.upper
-Funktion benötigt per Definition nur ein Argument, und so haben wir nur ein Iterable an sie übergeben. Wenn die von Ihnen übergebene Funktion jedoch zwei, drei oder n Argumente benötigt, dann müssen Sie zwei, drei oder n Iterablen an sie übergeben. Lassen Sie mich dies mit einem weiteren Beispiel verdeutlichen.
Angenommen, ich habe eine Liste von Kreisflächen, die ich irgendwo berechnet habe, alle auf fünf Dezimalstellen. Und ich muss jedes Element in der Liste auf seine Position in Dezimalstellen runden, das bedeutet, dass ich das erste Element in der Liste auf eine Dezimalstelle runden muss, das zweite Element in der Liste auf zwei Dezimalstellen, das dritte Element in der Liste auf drei Dezimalstellen usw. Mit map()
ist dies ein Kinderspiel. Sehen wir uns an, wie.
Python segnet uns bereits mit der eingebauten Funktion round()
, die zwei Argumente nimmt -- die Zahl, die gerundet werden soll, und die Anzahl der Dezimalstellen, auf die die Zahl gerundet werden soll. Da die Funktion zwei Argumente benötigt, müssen wir zwei Iterablen übergeben.
# Python 3
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 7)))
print(result)
Sehen Sie die Schönheit von map()
? Können Sie die Flexibilität ahnen, die dies hervorruft?
Die Funktion range(1, 7)
fungiert als zweites Argument für die Funktion round
(die Anzahl der erforderlichen Dezimalstellen pro Iteration). Während map
durch circle_areas
iteriert, wird während der ersten Iteration das erste Element von circle_areas
, 3.56773
, zusammen mit dem ersten Element von range(1,7)
, 1
an round
übergeben, wodurch es effektiv zu round(3.56773, 1)
wird. Während der zweiten Iteration wird das zweite Element von circle_areas
, 5.57668
, zusammen mit dem zweiten Element von range(1,7)
, 2
an round
übergeben, wodurch es zu round(5.57668, 2)
übersetzt wird. Dies geschieht, bis das Ende der circle_areas
-Liste erreicht ist.
Ich bin sicher, Sie fragen sich: "Was passiert, wenn ich ein Iterable übergebe, das kürzer oder länger als das erste Iterable ist? Das heißt, was passiert, wenn ich range(1, 3)
oder range(1, 9999)
als zweites Iterable in der obigen Funktion übergebe". Und die Antwort ist einfach: nichts! Okay, das stimmt nicht. "Nichts" passiert in dem Sinne, dass die map()
-Funktion keine Ausnahme auslöst, sie iteriert einfach über die Elemente, bis sie kein zweites Argument für die Funktion mehr findet, und dann hört sie einfach auf und gibt das Ergebnis zurück.
Wenn Sie zum Beispiel result = list(map(round, circle_areas, range(1, 3)))
auswerten, erhalten Sie keinen Fehler, selbst wenn sich die Länge von circle_areas
und die Länge von range(1, 3)
unterscheiden. Stattdessen macht Python Folgendes: Es nimmt das erste Element von circle_areas
und das erste Element von range(1,3)
und gibt es an round
weiter. round
wertet es aus und speichert das Ergebnis. Dann geht es weiter zur zweiten Iteration, dem zweiten Element von circle_areas
und dem zweiten Element von range(1,3)
, und round
speichert es erneut. Nun, in der dritten Iteration (circle_areas
hat ein drittes Element), nimmt Python das dritte Element von circle_areas
und versucht dann, das dritte Element von range(1,3)
zu nehmen, aber da range(1,3)
kein drittes Element hat, hört Python einfach auf und gibt das Ergebnis zurück, das in diesem Fall einfach [3.6, 5.58]
wäre.
Versuchen Sie es, probieren Sie es aus.
# Python 3
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 3)))
print(result)
Das Gleiche passiert, wenn circle_areas
kürzer als das zweite Iterable ist. Python stoppt einfach, wenn es das nächste Element in einem der Iterablen nicht finden kann.
Um unser Wissen über die map()
-Funktion zu festigen, werden wir sie verwenden, um unsere eigene benutzerdefinierte zip()
-Funktion zu implementieren. Die zip()
-Funktion ist eine Funktion, die eine Anzahl von Iterablen nimmt und dann ein Tupel erstellt, das jeweils die Elemente in den Iterablen enthält. Wie map()
gibt sie in Python 3 ein Generatorobjekt zurück, das durch Aufrufen der eingebauten list
-Funktion darauf leicht in eine Liste konvertiert werden kann. Verwenden Sie die folgende Interpretersitzung, um ein Gefühl für zip()
zu bekommen, bevor wir unsere eigene mit map()
erstellen.
# Python 3
my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [1, 2, 3, 4, 5]
results = list(zip(my_strings, my_numbers))
print(results)
Bonusfrage: Können Sie erraten, was passieren würde, wenn my_strings
und my_numbers
nicht die gleiche Länge hätten? Nein? Probieren Sie es aus! Ändern Sie die Länge eines von ihnen.
Jetzt zu unserer eigenen benutzerdefinierten zip()
-Funktion!
# Python 3
my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [1, 2, 3, 4, 5]
results = list(map(lambda x, y: (x, y), my_strings, my_numbers))
print(results)
Schauen Sie sich das an! Wir haben das gleiche Ergebnis wie zip
.
Haben Sie auch bemerkt, dass ich nicht einmal eine Funktion mit der Standardmethode def my_function()
erstellen musste? Das ist, wie flexibel map()
, und Python im Allgemeinen, ist! Ich habe einfach eine lambda
-Funktion verwendet. Das soll nicht heißen, dass das Verwenden der Standardfunktiondefinierungsmethode (von def function_name()
) nicht erlaubt ist, das ist es immer noch. Ich wollte einfach weniger Code schreiben (also "Pythonic" sein).
Das war alles über map
. Weiter zu filter()
Filter
Während map()
jedes Element im Iterable durch eine Funktion leitet und das Ergebnis aller Elemente zurückgibt, die durch die Funktion geleitet wurden, erfordert filter()
zuerst, dass die Funktion boolesche Werte (true oder false) zurückgibt und leitet dann jedes Element im Iterable durch die Funktion und "filtert" diejenigen heraus, die false sind. Es hat die folgende Syntax:
filter(func, iterable)
Die folgenden Punkte sind in Bezug auf filter()
zu beachten:
- Im Gegensatz zu
map()
ist nur ein Iterable erforderlich. - Das Argument
func
muss einen booleschen Typ zurückgeben. Wenn dies nicht der Fall ist, gibtfilter
einfach das übergebeneiterable
zurück. Da nur ein Iterable erforderlich ist, ist impliziert, dassfunc
nur ein Argument nehmen darf. filter
leitet jedes Element im Iterable durchfunc
und gibt nur diejenigen zurück, die true auswerten. Ich meine, es steht direkt im Namen -- ein "Filter".
Sehen wir uns einige Beispiele an.
Das folgende ist eine Liste (iterable
) der Punktzahlen von 10 Studenten in einer Chemieprüfung. Lassen Sie uns mit filter
die herausfiltern, die bestanden haben, mit Punktzahlen über 75.
# Python 3
scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65]
def is_A_student(score):
return score > 75
over_75 = list(filter(is_A_student, scores))
print(over_75)
Das nächste Beispiel wird ein Palindrome-Detektor sein. Ein "Palindrom" ist ein Wort, Satz oder eine Folge, die rückwärts gelesen dasselbe ergibt wie vorwärts. Lassen Sie uns Wörter herausfiltern, die Palindrome sind, aus einem Tuple (iterable
) von vermuteten Palindromen.
# Python 3
dromes = ("demigod", "rewire", "madam", "freer", "anutforajaroftuna", "kiosk")
palindromes = list(filter(lambda word: word == word[::-1], dromes))
print(palindromes)
Was ['madam', 'anutforajaroftuna']
ausgeben sollte.
Ziemlich cool, oder? Schließlich reduce()
Reduce
reduce
wendet eine Funktion mit zwei Argumenten kumulativ auf die Elemente eines Iterables an, optional beginnend mit einem Anfangsargument. Es hat die folgende Syntax:
reduce(func, iterable[, initial])
Dabei ist func
die Funktion, auf die jedes Element im iterable
kumulativ angewendet wird, und initial
ist der optionale Wert, der vor den Elementen des Iterables in der Berechnung platziert wird und als Standard dient, wenn das Iterable leer ist. Folgendes sollte in Bezug auf reduce()
beachtet werden:
1. func
erfordert zwei Argumente, wobei das erste das erste Element im iterable
ist (wenn initial
nicht angegeben ist) und das zweite Element im iterable
. Wenn initial
angegeben ist, wird es zum ersten Argument von func
und das erste Element im iterable
wird zum zweiten Element.
2. reduce
"reduziert" (ich weiß, vergeben Sie mir) iterable
auf einen einzigen Wert.
Wie üblich, lassen Sie uns einige Beispiele sehen.
Lassen Sie uns unsere eigene Version von Pythons eingebauter sum()
-Funktion erstellen. Die sum()
-Funktion gibt die Summe aller Elemente in dem übergebenen Iterable zurück.
# Python 3
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers)
print(result)
Das Ergebnis, wie Sie es erwarten werden, ist 68
.
Was ist passiert?
Wie immer geht es um Iterationen: reduce
nimmt die ersten beiden Elemente in numbers
und übergibt sie respektive an custom_sum
. custom_sum
berechnet deren Summe und gibt sie an reduce
zurück. reduce
nimmt dieses Ergebnis und wendet es als erstes Element an custom_sum
an und nimmt das nächste Element (dritte) in numbers
als zweites Element zu custom_sum
. Es macht dies kontinuierlich (kumulativ), bis numbers
erschöpft ist.
Sehen wir uns an, was passiert, wenn ich den optionalen initial
-Wert verwende.
# Python 3
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers, 10)
print(result)
Das Ergebnis, wie Sie erwarten werden, ist 78
, da reduce
zunächst 10
als erstes Argument an custom_sum
verwendet.
Das war alles über Pythons Map, Reduce, und Filter. Versuchen Sie die unten stehenden Übungen, um Ihr Verständnis für jede Funktion zu festigen.
Übung
In dieser Übung werden Sie jeweils map
, filter
, und reduce
verwenden, um fehlerhaften Code zu beheben.
from functools import reduce
# Use map to print the square of each numbers rounded
# to three decimal places
my_floats = [4.35, 6.09, 3.25, 9.77, 2.16, 8.88, 4.59]
# Use filter to print only the names that are less than
# or equal to seven letters
my_names = ["olumide", "akinremi", "josiah", "temidayo", "omoseun"]
# Use reduce to print the product of these numbers
my_numbers = [4, 6, 9, 23, 5]
# Fix all three respectively.
map_result = list(map(lambda x: x, my_floats))
filter_result = list(filter(lambda name: name, my_names, my_names))
reduce_result = reduce(lambda num1, num2: num1 * num2, my_numbers, 0)
print(map_result)
print(filter_result)
print(reduce_result)
#### Map
from functools import reduce
my_floats = [4.35, 6.09, 3.25, 9.77, 2.16, 8.88, 4.59]
my_names = ["olumide", "akinremi", "josiah", "temidayo", "omoseun"]
my_numbers = [4, 6, 9, 23, 5]
map_result = list(map(lambda x: round(x ** 2, 3), my_floats))
filter_result = list(filter(lambda name: len(name) <= 7, my_names))
reduce_result = reduce(lambda num1, num2: num1 * num2, my_numbers)
print(map_result)
print(filter_result)
print(reduce_result)
test_output_contains("[18.922, 37.088, 10.562, 95.453, 4.666, 78.854, 21.068]")
test_output_contains("['olumide', 'josiah', 'omoseun']")
test_output_contains("24840")
success_msg("Congrats! Nice work.")
This site is generously supported by DataCamp. DataCamp offers online interactive Python Tutorials for Data Science. Join over a million other learners and get started learning Python for data science today!