Функция partial появилась в стандартной библиотеке Python (модуль functools), начиная с Python 2.5, чтобы реализовать паттерн каррирования и частичное применение аргументов к функции. partialmethod появился с Python 3.4 для аналогичного применения в методах классов.
Часто в реальных проектах возникает задача зафиксировать часть аргументов у функции, чтобы получить новую функцию с "запомненными" значениями некоторых аргументов. Это удобно для колбеков, шаблонов передачи аргументов, или для повышения читаемости кода, особенно в функциональном программировании и при использовании API, ожидающих определенный стиль функций.
Функция partial возвращает новый объект-функцию, в которую "жёстко" пробиты (зафиксированы) некоторые из переданных аргументов или ключевых аргументов. partialmethod реализует тот же подход для методов классов, корректно поддерживая механику передачи self/cls.
Пример кода:
from functools import partial, partialmethod def power(base, exponent): return base ** exponent # Фиксируем степень = 2 square = partial(power, exponent=2) print(square(5)) # 25 class Math: def power(self, base, exponent): return base ** exponent square = partialmethod(power, exponent=2) m = Math() print(m.square(5)) # 25
Ключевые особенности:
Можно ли использовать partial для методов класса, чтобы получить аналог partialmethod?
Нет, partial не обрабатывает self/cls корректно, при применении к методу класса не работает ожидаемым образом: self не будет автоматически подставляться.
class C: def m(self, x, y): return x + y wrong = partial(m, y=2) # Неправильно!
При вызове c.wrong(5) возникнет TypeError, потому что self не будет передан автоматически.
Созданный через partial объект — это функция?
Да, результат работы partial — объект, который ведет себя как функция, поддерживает вызов, имя, докстринг и т. д., но это не обычная функция, это объект класса partial, реализующий протокол call.
from functools import partial f = partial(pow, 2) print(type(f)) # <class 'functools.partial'>
Работает ли partial с аргументами по умолчанию функции?
Да, partial может "переписать" значения по умолчанию во внутренней функции; если переданы в partial аргументы, они приоритетны над значениями по умолчанию в самой функции. Однако важно не дублировать значения, иначе будет ошибка.
Разработчик применяет partial для метода класса вместо partialmethod:
class MyClass: def f(self, x, y): ... squared = partial(f, y=2) ... obj = MyClass() obj.squared(5) # TypeError: missing 1 required positional argument: 'self'
Плюсы:
Минусы:
Вместо этого применяется partialmethod:
from functools import partialmethod class MyClass: def f(self, x, y): return x + y squared = partialmethod(f, y=2) obj = MyClass() print(obj.squared(5)) # 7
Плюсы:
Минусы: