Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fill specific positional arguments with partial in python?

Tags:

python

Basically, what I'd like to do is:

>>> from functools import partial >>> partial(str.startswith, prefix='a')('a') Traceback (most recent call last):   File "<stdin>", line 1, in <module> TypeError: startswith() takes no keyword arguments 

But more generally the question is, how to fill specific positional arguments with partial.

P.S. I do realize that I can use a lambda instead.

like image 546
newtover Avatar asked Oct 18 '11 17:10

newtover


People also ask

How do you use partial in Python?

You can create partial functions in python by using the partial function from the functools library. Partial functions allow one to derive a function with x parameters to a function with fewer parameters and fixed values set for the more limited function. This code will return 8.

How do you pass a positional argument in Python?

Functions can accept a variable number of positional arguments by using *args in the def statement. You can use the items from a sequence as the positional arguments for a function with the * operator. Using the * operator with a generator may cause your program to run out of memory and crash.

How do you fix takes 1 positional argument but 2 were given?

The “takes 1 positional argument but 2 were given” error is raised when you try to pass an argument through a method in a class without also specifying “self” as an argument. You solve this error by adding “self” as an argument to all the methods in a class.

Can you mix positional and keyword arguments?

Keyword arguments aren't just useful for functions that accept any number of positional arguments (like print ). You can pass keyword arguments to just about any function in Python. We're passing in one positional argument and one keyword argument. That start=1 works with sum because start is the name of that argument.


2 Answers

It cannot be done. You have to make a wrapper function.

Ostensibly, you would use keyword arguments, as you tried to do - that's what they're for, right? Unfortunately, as you've discovered, python's standard library functions do not take named parameters. Thus, it is not possible given the current implementation of partial without making another function to run interference.

According to the acceptance of PEP 309, what was accepted for inclusion was "a partial() type constructor binding leftmost positional arguments and any keywords." Furthermore, it states:

Note that when the object is called as though it were a function, positional arguments are appended to those provided to the constructor, and keyword arguments override and augment those provided to the constructor.

Positional arguments, keyword arguments or both can be supplied at when creating the object and when calling it.

Because additional positional arguments are appended, there would be no way to supply some preceding positional argument (by this implementation).

However, it goes on:

Partially applying arguments from the right, or inserting arguments at arbitrary positions creates its own problems, but pending discovery of a good implementation and non-confusing semantics, I don't think it should be ruled out.

So, it apparently could be on the table, but as it stands, it is not implemented that way.

For the sake of disclosure, emphasis in quotes above was my own.

like image 62
Nate Avatar answered Sep 28 '22 13:09

Nate


If you really need this you can use rpartial from funcy 3rd-party library.

Its code is here:

def rpartial(func, *args):     return lambda *a: func(*(a + args)) 

So, your case can be handled as following:

>>> startswith_a = rpartial(str.startswith, 'a') >>> startswith_a('abc') True >>> startswith_a('def') False 
like image 38
oblalex Avatar answered Sep 28 '22 14:09

oblalex