Partials sind unglaublich nützlich.
Zum Beispiel in einer 'Pipeline'-Folge von Funktionsaufrufen (in der der von einer Funktion zurückgegebene Wert das an die nächste übergebene Argument ist).
Manchmal erfordert eine Funktion in einer solchen Pipeline ein einzelnes Argument , aber die unmittelbar vorgelagerte Funktion gibt zwei Werte zurück .
In diesem Szenario functools.partial
können Sie diese Funktionspipeline möglicherweise intakt halten.
Hier ist ein spezielles, isoliertes Beispiel: Angenommen, Sie möchten einige Daten nach der Entfernung jedes Datenpunkts von einem Ziel sortieren:
# create some data
import random as RND
fnx = lambda: RND.randint(0, 10)
data = [ (fnx(), fnx()) for c in range(10) ]
target = (2, 4)
import math
def euclid_dist(v1, v2):
x1, y1 = v1
x2, y2 = v2
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
Um diese Daten nach Entfernung vom Ziel zu sortieren, möchten Sie natürlich Folgendes tun:
data.sort(key=euclid_dist)
aber du nicht - die Art der Methode Schlüsselparameter nur Funktionen übernehmen , die einen nehmen einzelnes Argument.
Schreiben Sie also euclid_dist
als Funktion neu, indem Sie einen einzelnen Parameter verwenden:
from functools import partial
p_euclid_dist = partial(euclid_dist, target)
p_euclid_dist
akzeptiert jetzt ein einziges Argument,
>>> p_euclid_dist((3, 3))
1.4142135623730951
Jetzt können Sie Ihre Daten sortieren, indem Sie die Teilfunktion für das Schlüsselargument der Sortiermethode übergeben:
data.sort(key=p_euclid_dist)
# verify that it works:
for p in data:
print(round(p_euclid_dist(p), 3))
1.0
2.236
2.236
3.606
4.243
5.0
5.831
6.325
7.071
8.602
Zum Beispiel ändert sich eines der Argumente der Funktion in einer äußeren Schleife, wird jedoch während der Iteration in der inneren Schleife festgelegt. Bei Verwendung eines Teils müssen Sie den zusätzlichen Parameter während der Iteration der inneren Schleife nicht übergeben, da die modifizierte (Teil-) Funktion dies nicht erfordert.
>>> from functools import partial
>>> def fnx(a, b, c):
return a + b + c
>>> fnx(3, 4, 5)
12
Erstellen Sie eine Teilfunktion (mit dem Schlüsselwort arg)
>>> pfnx = partial(fnx, a=12)
>>> pfnx(b=4, c=5)
21
Sie können auch eine Teilfunktion mit einem Positionsargument erstellen
>>> pfnx = partial(fnx, 12)
>>> pfnx(4, 5)
21
Dies wird jedoch ausgelöst (z. B. Erstellen eines Teils mit einem Schlüsselwortargument und anschließendes Aufrufen mit Positionsargumenten).
>>> pfnx = partial(fnx, a=12)
>>> pfnx(4, 5)
Traceback (most recent call last):
File "<pyshell#80>", line 1, in <module>
pfnx(4, 5)
TypeError: fnx() got multiple values for keyword argument 'a'
Ein weiterer Anwendungsfall: Schreiben von verteiltem Code mithilfe der Python- multiprocessing
Bibliothek. Ein Pool von Prozessen wird mit der Pool-Methode erstellt:
>>> import multiprocessing as MP
>>> # create a process pool:
>>> ppool = MP.Pool()
Pool
hat eine Map-Methode, benötigt aber nur eine einzige iterable. Wenn Sie also eine Funktion mit einer längeren Parameterliste übergeben müssen, definieren Sie die Funktion als Teil neu, um alle bis auf eine zu reparieren:
>>> ppool.map(pfnx, [4, 6, 7, 8])
extra_args