Как проверить, что functools.partial создает ожидаемый объект функции
При переходе от одного API к другому иногда бывает полезно сопоставить похожие ключевые слова в каждом API, позволяя одному API контроллера гибко отправлять данные в другие библиотеки, не требуя от пользователя возиться с различными API.
Предположим, какая-то библиотека, other_api
, имеет метод, называемый "logarithm"
и аргумент ключевого слова для базы - это то, что мне нужно выделить из моего кода, например "log_base_val"
; чтобы использовать его из other_api
Мне нужно напечатать (например):
other_api.logarithm(log_base_val=math.e)
Рассмотрим класс игрушек вот так:
import other_api
import math
import functools
class Foo(object):
_SUPPORTED_ARGS = {"base":"log_base_val"}
def arg_binder(self, other_api_function_name, **kwargs):
other_api_function = getattr(other_api, other_api_function_name)
other_api_kwargs = {_SUPPORTED_ARGS[k]:v for k,v in kwargs.iteritems()}
return functools.partial(other_api_function, **other_api_kwargs)
С Foo
Я могу сопоставить какой-то другой API, где этот аргумент всегда вызывается base
, как это:
f = Foo()
ln = f.arg_binder("logarithm", base=math.e)
а также ln
логически эквивалентно (с log_base_val=math.e
в kwargs
, от functools
):
other_api.logarithm(*args, **kwargs)
Тем не менее, вручную сделать один и тот же аргумент связывания, вызвав functools
приведет к различным функциям объектов:
In [10]: import functools
In [11]: def foo(a, b):
....: return a + b
....:
In [12]: f1 = functools.partial(foo, 2)
In [13]: f2 = functools.partial(foo, 2)
In [14]: id(f1)
Out[14]: 67615304
In [15]: id(f2)
Out[15]: 67615568
Итак, тестирование для f1 == f2
не удастся, как задумано:
In [16]: f1 == f2
Out[16]: False
Таким образом, вопрос заключается в следующем: каков предписанный способ проверить, привела ли функция привязки аргумента к правильному объекту выходной функции?
1 ответ
func
атрибут на partial()
объект является ссылкой на исходный объект функции:
f1.func is f2.func
Сами объекты функций не реализуют __eq__
метод, так что вы можете просто использовать is
проверить на личность.
Точно так же partial().args
а также partial().keywords
содержит аргументы и ключевые слова аргументы, которые будут переданы функции при вызове.
Демо-версия:
>>> from functools import partial
>>> def foo(a, b):
... return a + b
...
>>> f1 = partial(foo, 2)
>>> f2 = partial(foo, 2)
>>> f1.func is f2.func
True
>>> f1.args
(2,)
>>> f2.args
(2,)
>>> f1.keywords is None
True
>>> f2.keywords is None
True