Example use:
def f(a, b, c, d): 
    print(a, b, c, d, sep = '&')
f(1,2,3,4)
>>> 1&2&3&4
f(*[1, 2, 3, 4])
>>> 1&2&3&4
Where in the python documentation is * explained?
Example use:
def f(a, b, c, d): 
    print(a, b, c, d, sep = '&')
f(1,2,3,4)
>>> 1&2&3&4
f(*[1, 2, 3, 4])
>>> 1&2&3&4
Where in the python documentation is * explained?
The *args calling convention is documented in the Expressions reference:
If the syntax
*expressionappears in the function call,expressionmust evaluate to an iterable. Elements from this iterable are treated as if they were additional positional arguments; if there are positional arguments x1, ..., xN, andexpressionevaluates to a sequence y1, ..., yM, this is equivalent to a call with M+N positional arguments x1, ..., xN, y1, ..., yM.
So, since you used [1, 2, 3, 4] as the expression, which is an iterable, and there were no other positional arguments, it is treated as a call with M=0 and N=4, for a total of 4 positional arguments.
You can thus also call your function as f(1, 2, *[3, 4]) or any other combination of iterable and positional arguments, provided the iterable comes after the positionals.
 
    
    Just an addition to very simply expand on the combination of unnamed and named arguments.
This is the general order you want to keep in mind:
def func(arg_1, ..., arg_N, *args, kwarg_1, ..., kwarg_M, **kwargs):
    # do stuff
    return True
Where, in most typical cases;
arg_i is an unnamed argument,args is a list, hence a set of unnamed arguments,kwarg_j is a named argument,kwargs is a dictionary, hence a set of named arguments.