Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function that accepts both expanded arguments and tuple

Tags:

python

Is there a Pythonic way to create a function that accepts both separate arguments and a tuple? i.e to achieve something like this:

def f(*args):
    """prints 2 values 
            f(1,2)
                1 2
            f( (1,2) )
                1 2"""
    if len(args) == 1:
        if len(args[0]) != 2:
            raise Exception("wrong number of arguments")
        else:
            print args[0][0],args[0][1]
    elif len(args) == 2:
        print args[0],args[1]
    else:
            raise Exception("wrong number of arguments")
like image 371
B-K Avatar asked Jan 27 '17 16:01

B-K


People also ask

Which function takes tuple as argument?

Example: Pass a Tuple as an Argument using *args Syntax Unpacking in Python uses *args syntax. As functions can take an arbitrary number of arguments, we use the unpacking operator * to unpack the single argument into multiple arguments. This is a special way of receiving parameters to a function as a tuple.

How do you pass a tuple as an argument to a function?

The use of the asterisk * in the call to the function unpacks the tuple and passes its items as positional arguments to the function.

How can you accept multiple arguments into a function?

The * symbol is used to pass a variable number of arguments to a function. Typically, this syntax is used to avoid the code failing when we don't know how many arguments will be sent to the function.


1 Answers

First of all I don't know if it is very wise to do so. Say a person calls a function like:

f(*((1,4),(2,5)))

As you can see the tuple contains two elements. But now for some reason, the person calls it with only one element (because for instance the generator did not generated two elements):

f(*((1,4),))

Then the user would likely want your function to report this, but now it will simply accept it (which can lead to complicated and unexpected behavior). Okay printing the elements of course will not do much harm. But in a general case the consequences might be more severe.

Nevertheless an elegant way to do this is making a simple decorator that first checks if one element is fed it checks if one tuple element is feeded and if so expands it:

def one_tuple(f):
    def g(*args):
        if len(args) == 1 and isinstance(args[0],tuple):
            return f(*args[0])
        else:
            return f(*args)
    return g

And apply it to your f:

@one_tuple
def f(*args):
    if len(args) == 2:
        print args[0],args[1]
    else:
        raise Exception("wrong number of arguments")

The decorator one_tuple thus checks if one tuple is fed, and if so unpacks it for you before passing it to your f function.

As a result f does not have to take the tuple case into account: it will always be fed expanded arguments and handle these (of course the opposite could be done as well).

The advantage of defining a decorator is its reuse: you can apply this decorator to all kinds of functions (and thus make it easier to implement these).

like image 50
Willem Van Onsem Avatar answered Oct 13 '22 03:10

Willem Van Onsem