it-swarm.com.de

Verwendung von Filtern, Zuordnen und Reduzieren in Python 3

filter, map und reduce funktionieren perfekt in Python 2. Hier ein Beispiel:

>>> def f(x):
        return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]

>>> def cube(x):
        return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

>>> def add(x,y):
        return x+y
>>> reduce(add, range(1, 11))
55

In Python 3 erhalte ich jedoch folgende Ausgaben:

>>> filter(f, range(2, 25))
<filter object at 0x0000000002C14908>
>>> map(cube, range(1, 11))
<map object at 0x0000000002C82B70>
>>> reduce(add, range(1, 11))
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    reduce(add, range(1, 11))
NameError: name 'reduce' is not defined

Ich würde mich freuen, wenn mir jemand erklären könnte, warum das so ist.

Screenshot des Codes für mehr Klarheit:

 IDLE sessions of Python 2 and 3 side-by-side

252
Dick Lucas

Informationen zu den Änderungen finden Sie in What's New in Python 3.0 . Sie sollten es sorgfältig lesen, wenn Sie von 2.x zu 3.x wechseln, da eine Menge geändert wurde.

Die ganze Antwort hier sind Zitate aus der Dokumentation.

Ansichten und Iteratoren statt Listen

Einige bekannte APIs geben keine Listen mehr zurück:

  • [...]
  • map() und filter() Iteratoren zurückgeben. Wenn Sie wirklich eine Liste benötigen, können Sie z. list(map(...)), aber eine bessere Lösung ist häufig die Verwendung eines Listenverständnisses (insbesondere wenn der ursprüngliche Code Lambda verwendet) oder das Schreiben des Codes, sodass keine Liste erforderlich ist. Besonders knifflig ist map() für die Nebenwirkungen der Funktion; Die korrekte Umwandlung ist die Verwendung einer regulären for-Schleife (da das Erstellen einer Liste nur verschwenderisch wäre).
  • [...]

Builtins

  • [...]
  • reduce() wurde entfernt. Verwenden Sie functools.reduce() , wenn Sie es wirklich brauchen. In 99 Prozent der Fälle ist eine explizite for-Schleife jedoch besser lesbar.
  • [...]
290
nhahtdh

Die Funktionalität von map und filter wurde absichtlich geändert, um Iteratoren zurückzugeben, und die Reduktion wurde aus dem eingebauten Zustand entfernt und in functools.reduce platziert.

Für filter und map können Sie sie mit list() umschließen, um die Ergebnisse wie zuvor anzuzeigen.

>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> list(filter(f, range(2, 25)))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> list(map(cube, range(1, 11)))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> import functools
>>> def add(x,y): return x+y
...
>>> functools.reduce(add, range(1, 11))
55
>>>

Die Empfehlung lautet nun, dass Sie Ihre Verwendung von Map und Filter durch Generatorenausdrücke oder Listenverständnisse ersetzen. Beispiel:

>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> [i for i in range(2, 25) if f(i)]
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> [cube(i) for i in range(1, 11)]
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>>

Sie sagen, dass für Schleifen 99 Prozent der Zeit einfacher zu lesen sind als zu reduzieren, aber ich würde einfach bei functools.reduce bleiben.

Edit: Die 99-Prozent-Zahl wird direkt von der von Guido van Rossum erstellten Seite What's New in Python 3.0 abgerufen.

74
Joshua D. Boyd

Als Nachtrag zu den anderen Antworten klingt dies nach einem guten Anwendungsfall für einen Kontextmanager, der die Namen dieser Funktionen auf Funktionen zurückgibt, die eine Liste zurückgeben und reduce im globalen Namensraum einführen.

Eine schnelle Implementierung könnte so aussehen:

from contextlib import contextmanager    

@contextmanager
def noiters(*funcs):
    if not funcs: 
        funcs = [map, filter, Zip] # etc
    from functools import reduce
    globals()[reduce.__name__] = reduce
    for func in funcs:
        globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar))
    try:
        yield
    finally:
        del globals()[reduce.__name__]
        for func in funcs: globals()[func.__name__] = func

Mit einer Verwendung, die so aussieht:

with noiters(map):
    from operator import add
    print(reduce(add, range(1, 20)))
    print(map(int, ['1', '2']))

Welche drucke:

190
[1, 2]

Nur meine 2 Cent :-)

Vergessen Sie nicht, die reduce in Ihren Code zu importieren, da die functools-Methode aus der integrierten Funktion von Python3 entfernt wurde. Bitte sehen Sie sich den Code-Ausschnitt unten an.

import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
3
Bikash Singh

Hier sind die Beispiele für Funktionen zum Filtern, Zuordnen und Reduzieren.

zahlen = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]

//Filter

oddNumbers = Liste (Filter (Lambda x: x% 2! = 0, Zahlen))

print (ungeradeNummern)

//Karte

multiplyOf2 = Liste (Karte (Lambda x: x * 2, Zahlen))

drucken (multipliplyOf2)

//Reduzieren

Die Reduzierungsfunktion wurde aus den in Python 3 integrierten Funktionen entfernt, da sie nicht häufig verwendet wird. Sie ist weiterhin im functools-Modul verfügbar.

von functools import reduzieren

sumOfNumbers = verkleinern (Lambda x, y: x + y, Zahlen)

print (sumOfNumbers)

0
Yogendra Singh