Search code examples
pythonsyntaxparameter-passingvariadic-functionsargument-unpacking

What does ** (double star/asterisk) and * (star/asterisk) do for parameters?


What do *args and **kwargs mean in these function definitions?

def foo(x, y, *args):
    pass

def bar(x, y, **kwargs):
    pass

See What do ** (double star/asterisk) and * (star/asterisk) mean in a function call? for the complementary question about arguments.


Solution

  • The *args and **kwargs are common idioms to allow an arbitrary number of arguments to functions, as described in the section more on defining functions in the Python tutorial.

    The *args will give you all positional arguments as a tuple:

    def foo(*args):
        for a in args:
            print(a)        
    
    foo(1)
    # 1
    
    foo(1, 2, 3)
    # 1
    # 2
    # 3
    

    The **kwargs will give you all keyword arguments as a dictionary:

    def bar(**kwargs):
        for a in kwargs:
            print(a, kwargs[a])  
    
    bar(name='one', age=27)
    # name one
    # age 27
    

    Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:

    def foo(kind, *args, bar=None, **kwargs):
        print(kind, args, bar, kwargs)
    
    foo(123, 'a', 'b', apple='red')
    # 123 ('a', 'b') None {'apple': 'red'}
    

    It is also possible to use this the other way around:

    def foo(a, b, c):
        print(a, b, c)
    
    obj = {'b':10, 'c':'lee'}
    
    foo(100, **obj)
    # 100 10 lee
    

    Another usage of the *l idiom is to unpack argument lists when calling a function.

    def foo(bar, lee):
        print(bar, lee)
    
    baz = [1, 2]
    
    foo(*baz)
    # 1 2
    

    In Python 3 it is possible to use *l on the left side of an assignment (Extended Iterable Unpacking), though it gives a list instead of a tuple in this context:

    first, *rest = [1, 2, 3, 4]
    # first = 1
    # rest = [2, 3, 4]
    

    Also Python 3 adds a new semantic (refer PEP 3102):

    def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
        pass
    

    Such function accepts only 3 positional arguments, and everything after * can only be passed as keyword arguments.

    Note:

    A Python dict, semantically used for keyword argument passing, is arbitrarily ordered. However, in Python 3.6+, keyword arguments are guaranteed to remember insertion order. "The order of elements in **kwargs now corresponds to the order in which keyword arguments were passed to the function." - What’s New In Python 3.6. In fact, all dicts in CPython 3.6 will remember insertion order as an implementation detail, and this becomes standard in Python 3.7.