частки неймовірно корисні.
Наприклад, у послідовності виклику функцій (у якій викладено трубу) (у якому повернене значення з однієї функції є аргументом, переданим наступному).
Іноді функція в такому конвеєрі вимагає одного аргументу , але функція, що знаходиться негайно від неї, повертає два значення .
У цьому сценарії, functools.partial
можливо, ви зможете зберегти цю функцію конвеєра недоторканою.
Ось конкретний, ізольований приклад: припустимо, ви хочете сортувати деякі дані по відстані кожної точки даних від якоїсь цілі:
# 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)
Щоб сортувати ці дані за відстанню від цілі, ви, звичайно, хотіли б це зробити:
data.sort(key=euclid_dist)
але ви не можете - ключовий параметр методу сортування приймає лише функції, які беруть один аргумент.
тому перепишіть euclid_dist
як функцію, що приймає один параметр:
from functools import partial
p_euclid_dist = partial(euclid_dist, target)
p_euclid_dist
тепер приймає єдиний аргумент,
>>> p_euclid_dist((3, 3))
1.4142135623730951
тож тепер ви можете сортувати свої дані, передавши часткову функцію для ключового аргументу методу сортування:
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
Або, наприклад, один з аргументів функції змінюється у зовнішньому циклі, але фіксується під час ітерації у внутрішньому циклі. Використовуючи частковий, вам не доведеться передавати додатковий параметр під час ітерації внутрішнього циклу, оскільки змінена (часткова) функція цього не вимагає.
>>> from functools import partial
>>> def fnx(a, b, c):
return a + b + c
>>> fnx(3, 4, 5)
12
створити часткову функцію (використовуючи ключове слово arg)
>>> pfnx = partial(fnx, a=12)
>>> pfnx(b=4, c=5)
21
Ви також можете створити часткову функцію з позиційним аргументом
>>> pfnx = partial(fnx, 12)
>>> pfnx(4, 5)
21
але це буде кинутим (наприклад, створення часткового аргументу ключового слова, а потім виклик за допомогою позиційних аргументів)
>>> 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'
інший випадок використання: запис розподіленого коду за допомогою multiprocessing
бібліотеки python . Пул процесів створюється за допомогою методу Pool:
>>> import multiprocessing as MP
>>> # create a process pool:
>>> ppool = MP.Pool()
Pool
має метод карти, але він займає лише один ітерабельний, тому, якщо вам потрібно передати функцію з більш довгим списком параметрів, повторно визначте функцію як часткову, щоб виправити всі, крім одного:
>>> ppool.map(pfnx, [4, 6, 7, 8])
extra_args
змінну