When going from one API to another it can sometimes be helpful to map between similar keywords in each API, allowing one controller API to flexibly dispatch to other libraries without needing the user to fuss around with the different API's under the hood.
Assume some library, other_api
, has a method called "logarithm"
, and the keyword argument for the base is something I need to factor out of my code, like "log_base_val"
; so that to use it from other_api
I need to type (for example):
other_api.logarithm(log_base_val=math.e)
Consider a toy class like this:
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)
With Foo
, I can map some other API, where this argument is always called base
, like this:
f = Foo()
ln = f.arg_binder("logarithm", base=math.e)
and ln
is logically equivalent to (with log_base_val=math.e
in kwargs
, from functools
):
other_api.logarithm(*args, **kwargs)
However, manually making the same argument bind by invoking functools
will lead to different function objects:
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
So testing for f1 == f2
won't succeed as intended:
In [16]: f1 == f2
Out[16]: False
So the question is: what is the prescribed way to test whether the argument binding function has resulted in the correct output function object?
The func
attribute on the partial()
object is a reference to the original function object:
f1.func is f2.func
Function objects themselves don't implement a __eq__
method, so you may as well just use is
to test for identity.
Similarly, the partial().args
and partial().keywords
contain the arguments and keyword arguments to be passed to the function when called.
Demo:
>>> 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With