简体   繁体   中英

Most pythonic way to write a function to either pass in arguments or a tuple of arguments

What is a most pythonic way to write a function to either pass in arguments or a tuple/list of arguments?

For example, a function add could either take in an argument of add(1, 2) or add((1, 2)) and both output 3 .

What I have so far: (it works, but does not look nice)

def add(*args):
    if len(args) == 1:
        return (args[0][0] + args[0][1])
    if len(args) == 2:
        return args[0] + args[1]
    else:
        print "error: add takes in one or two arguments"

What I don't like about it is:

  1. I have to print the error about passing in one or two arguments
  2. The args[0][0] looks very unreadable
  3. This way, it is hard to tell what the arguments passed in represent (they don't have names)

I dont know if this is the most "pythonic" way but it will do what you want:

def add(a, b=None):
    return a+b if b is not None else sum(a)

If your function takes a specific number of arguments, then the most pythonic way to do this is to not do it. Rather if the user has a tuple with the arguments, you make them unpack them when they call the function. Eg

def add(a, b):
   return a + b

Then the caller can do

add(1,2)

or

t = (1,2)
add(*t)

The only time you want to accept either a sequence of params or individual params is when you can have any arbitrary (non-zero) number of arguments (eg the max and min builtin functions) in which case you'd just use *args

If you can only take a finite number of arguments, it makes more sense to ask for those specifically. If you can accept an arbitrary number of arguments, then the *args paradigm works well if you loop through it. Mixing and matching those two aren't very elegant.

def add(*args):
    total = 0
    for i in args:
        total += i
    return total

>>> add(1, 2, 3)
6

(I know we could just use sum() there, but I'm trying to make it look a bit more general)

In the spirit of python duck typing, if you see 1 argument, assume its something that expands to 2 arguments. If its then 2, assume its two things that add together. If it violates your rules, raise an exception like python would do on a function call.

def add(*args):
    if len(args) == 1:
        args = args[0]
    if len(args) != 2:
        raise TypeError("add takes 2 arguments or a tuple of 2 arguments")
    return args[0] + args[1]

A decorator would be best suited for this job.

from functools import wraps

def tupled_arguments(f):
    @wraps(f)  # keeps name, docstring etc. of f
    def accepts_tuple(tup, *args):
        if not args:  # only one argument given
            return f(*tup)
        return f(tup, *args)
    return accepts_tuple

@tupled_arguments
def add(a, b):
    return a + b

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM