functools.partial doesn't work without using named parameter
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Mar 25 03:04:47 EDT 2011
On Thu, 24 Mar 2011 23:30:29 -0700, Paddy wrote:
> Hi, I just found the following oddity where for function fsf1 I am
> forced to use a named parameter for correct evaluation and was wondering
> why it doesn't work, yet the example from the docs of wrapping int to
> create basetwo doesn't need this? The example:
>
>>>> from functools import partial
>>>> basetwo = partial(int, base=2)
>>>> basetwo('10010')
> 18
When you call basetwo, it gets passed one positional argument and one
keyword argument. The positional arguments are bound from left to right,
as is normal in Python:
int expects to be called like int(a, [base=]b)
int gets passed two arguments: int('10010', base=2)
so all is well. The string '10010' gets bound to the first argument, and
the keyword argument 2 gets bound to the second.
>>>> def fs(f, s): return [f(value) for value in s]
>
>>>> def f1(value): return value * 2
>
>>>> s = [0, 1, 2, 3]
>>>> fs(f1, s)
> [0, 2, 4, 6]
All these f's and s's give me a headache. It's easier to discuss if you
give them distinctive names: spam, ham, eggs are conventions in Python,
foo, bar, baz in some other languages.
>>>> fsf1 = partial(fs, f=f1)
>>>> fsf1(s)
> Traceback (most recent call last):
> File "<pyshell#24>", line 1, in <module>
> fsf1(s)
> TypeError: fs() got multiple values for keyword argument 'f'
fs expects to be called like fs(f, s). It gets called with one positional
argument, [0,1,2,3], which gets bound to the left-most parameter f, and
one keyword argument, f1, which *also* gets bound to the parameter f
(only by name this time, instead of by position).
>>>> # BUT
>>>> fsf1(s=s)
> [0, 2, 4, 6]
Now, because you're calling fsf1 with keyword argument, fs gets called:
fs(f=f1, s=[0,1,2,3])
--
Steven
More information about the Python-list
mailing list