Home > Articles

This chapter is from the book

This chapter is from the book

5.6 Functions Accepting All Inputs

By using both * and **, you can write a function that accepts any combination of arguments. The positional arguments are passed as a tuple and the keyword arguments are passed as a dictionary. For example:

# Accept variable number of positional or keyword arguments
def func(*args, **kwargs):
    # args is a tuple of positional args
    # kwargs is dictionary of keyword args
    ...

This combined use of *args and **kwargs is commonly used to write wrappers, decorators, proxies, and similar functions. For example, suppose you have a function to parse lines of text taken from an iterable:

def parse_lines(lines, separator=',', types=(), debug=False):
    for line in lines:
        ...
        statements
        ...

Now, suppose you want to make a special-case function that parses data from a file specified by filename instead. To do that, you could write:

def parse_file(filename, *args, **kwargs):
    with open(filename, 'rt') as file:
        return parse_lines(file, *args, **kwargs)

The benefit of this approach is that the parse_file() function doesn’t need to know anything about the arguments of parse_lines(). It accepts any extra arguments the caller provides and passes them along. This also simplifies the maintenance of the parse_file() function. For example, if new arguments are added to parse_lines(), those arguments will magically work with the parse_file() function too.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.