Закрытие в python с использованием functools.partial
from functools import partial
i = 0
f0 = partial(callback, i)
i = 1
f1 = partial(callback, i)
f0()
# 0
f1()
# 1
partial
похоже на лямбду, но оборачивает значение в этот момент в arg.Не оценивая его при вызове.
Обтекание только некоторых из аргументов
Да, частичное, позволит вам обернуть любое количество аргументов, а оставшиеся аргументы и kwargs могут быть переданырезультирующий частичный объект, так что он действует так, как если бы он вызывал оригинальную упакованную функцию ...
def callback(val1, val2):
print "{0} {1}".format(val1, val2)
i = 0
x = 8
f0 = partial(callback, i)
f0(x)
# 0 8
По сути, вы обернули callback(val1, val2)
в callback(val2)
с val1
, уже включенным в качестве замыкания.
Пример аналогичного эффекта с использованием лямбды
Если вы действительно хотите увидеть, как это сделать с лямбда-замыканием, вы можете понять, почему он становится уродливым, а частичное предпочтительным ...
f0 = (lambda val1: lambda val2: callback(val1, val2))(i)
Вы должны заключить переменную области во внешнюю область функции, а затем сослаться на эту область во внутренней лямбда-функции.ЮК.
Трассировки от исключений: частичное или лямбда-выражение против вложенных функций
Принимая во внимание другие ответы, я подумал, что хотел бы обрисовать еще одну причину использования частичного в отличие от лямбды или внутреннего / внешнегозакрытие функции.Имейте в виду, я имею в виду закрытие функции.functools.partial исправляет трассировку, которую вы получите, когда ваша упакованная функция вызовет исключение ...
Рассмотрим эту версию, которая увеличит деление на ноль:
def callback(val1, val2):
return val1 / val2
Обычный ауттер/ внутреннее закрытие
def wrapper(fn, val1):
def wrapped(val2):
return fn(val1, val2)
return wrapped
f0 = wrapper(callback, i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in wrapped
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero
лямбда-закрытие
f0 = (lambda val1: lambda val2: callback(val1, val2))(i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero
А теперь для functools.partial
f0 = partial(callback, i)
f0(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in callback
ZeroDivisionError: integer division or modulo by zero