A common use case for *args
in a function definition is to delegate processing to either a wrapped or inherited function. A typical example might be in a class's __init__
method
class A(object):
def __init__(self, b, c):
self.y = b
self.z = c
class B(A):
def __init__(self, a, *args, **kwargs):
super(B, self).__init__(*args, **kwargs)
self.x = a
Here, the a
parameter is processed by the child class after all other arguments (positional and keyword) are passed onto - and processed by - the base class.
For instance:
b = B(1, 2, 3)
b.x # 1
b.y # 2
b.z # 3
What happens here is the class B
__init__
function sees the arguments 1, 2, 3
. It knows it needs to take one positional argument (a
), so it grabs the first argument passed in (1
), so in the scope of the function a == 1
.
Next, it sees that it needs to take an arbitrary number of positional arguments (*args
) so it takes the rest of the positional arguments passed in (1, 2
) and stuffs them into *args
. Now (in the scope of the function) args == [2, 3]
.
Then, it calls class A
's __init__
function with *args
. Python sees the *
in front of args and "unpacks" the list into arguments. In this example, when class B
's __init__
function calls class A
's __init__
function, it will be passed the arguments 2, 3
(i.e. A(2, 3)
).
Finally, it sets its own x
property to the first positional argument a
, which equals 1
.