Как проверить, что 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
Другие вопросы по тегам