części niepełne są niezwykle przydatne.
Na przykład w sekwencji wywołań funkcji wyłożonych pionową kreską (w której wartość zwracana z jednej funkcji jest argumentem przekazywanym do następnej).
Czasami funkcja w takim potoku wymaga pojedynczego argumentu , ale funkcja bezpośrednio przed nią zwraca dwie wartości .
W tym scenariuszu functools.partial
może pozwolić na zachowanie tego potoku funkcji w stanie nienaruszonym.
Oto konkretny, odizolowany przykład: przypuśćmy, że chcesz posortować dane według odległości każdego punktu danych od jakiegoś celu:
# 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)
Aby posortować te dane według odległości od celu, chciałbyś oczywiście zrobić to:
data.sort(key=euclid_dist)
ale nie możesz - parametr key metody sort akceptuje tylko funkcje, które przyjmują jeden argument.
więc przepisz ponownie euclid_dist
jako funkcję pobierającą pojedynczy parametr:
from functools import partial
p_euclid_dist = partial(euclid_dist, target)
p_euclid_dist
teraz przyjmuje pojedynczy argument,
>>> p_euclid_dist((3, 3))
1.4142135623730951
więc teraz możesz sortować swoje dane, przekazując funkcję częściową dla argumentu klucza metody sort:
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
Lub na przykład jeden z argumentów funkcji zmienia się w pętli zewnętrznej, ale jest ustalany podczas iteracji w pętli wewnętrznej. Używając częściowej, nie musisz przekazywać dodatkowego parametru podczas iteracji wewnętrznej pętli, ponieważ zmodyfikowana (częściowa) funkcja tego nie wymaga.
>>> from functools import partial
>>> def fnx(a, b, c):
return a + b + c
>>> fnx(3, 4, 5)
12
utwórz funkcję częściową (używając słowa kluczowego arg)
>>> pfnx = partial(fnx, a=12)
>>> pfnx(b=4, c=5)
21
możesz również utworzyć funkcję częściową z argumentem pozycyjnym
>>> pfnx = partial(fnx, 12)
>>> pfnx(4, 5)
21
ale to zwróci (np. utworzenie częściowego argumentu słowa kluczowego, a następnie wywołanie za pomocą argumentów pozycyjnych)
>>> 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'
inny przypadek użycia: pisanie rozproszonego kodu przy użyciu multiprocessing
biblioteki Pythona . Pula procesów jest tworzona metodą Pool:
>>> import multiprocessing as MP
>>> # create a process pool:
>>> ppool = MP.Pool()
Pool
ma metodę mapowania, ale wymaga tylko jednej iteracji, więc jeśli chcesz przekazać funkcję z dłuższą listą parametrów, ponownie zdefiniuj funkcję jako częściową, aby naprawić wszystkie oprócz jednej:
>>> ppool.map(pfnx, [4, 6, 7, 8])
extra_args
zmienną