You can also be interested in:
What I've always really appreciated of python is the ability to give a function an arbitrary number of positional and keyword arguments, something that in PHP is not possible and is indeed very powerful.
When declaring a function, we can define 4 different types of arguments:
- required arguments
- optional arguments (a default is provided)
- excess positional arguments
- excess keyword arguments
def myfunc(a, b=3, *c, **d)
ais a required argument
bis an optional one since it's default value it's 3
- the single asterisk before the
cargument allows the function to accept any number of positional arguments
- the two asterisks before the
dargument allow the function to support arbitrary kewyword arguments
The order of such arguments is important!
As you've seen you're free to give the excess positional and keyword arguments the name you prefer, but as a python convention they are often called
Now let's see some examples to clarify these concepts.
>>> def sum(*args): ... s = 0 ... for arg in args: ... s += arg ... return s ... >>> sum(2, 3, 5) 10 >>> sum(1,2,3,4,5,6) 21
So we are able to write a simple function which can sum an arbitrary number of numbers, in PHP we should have used arrays instead.
We can use the
**kwargs argument to accept an arbitrary number of named options:
>>> def render(context, **kwargs): ... template = kwargs['template'] if 'template' in kwargs else 'my_default_template' ... # do something with your template ... print template ... >>> render() 'my_default_template' >>> render(template='custom_template') 'custom_template'
The excess keyword arguments were used for example in django to customize the generic views and make them adaptable to many different situations (https://docs.djangoproject.com/en/1.4/topics/generic-views/).
On the other hand, python code may call functions with any number of arguments using the same asterisk notation. Arguments passed in this way are expanded into a normal list of arguments. Take care when passing keyword arguments together with tuple as excess positional arguments, since python will apply the previously described ordering rules, so the positional arguments would come first! Some examples:
>>> def concatenate(a, b, c): ... return '%s%s%s' % (a, b, c) ... >>> concatenate(1, 2, 3) '123' >>> concatenate(5, b='K', c='g') '5Kg' >>> concatenate(5, *('K', 'g')) '5Kg' >>> concatenate(a=5, *('K', 'g')) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: concatenate() got multiple values for keyword argument 'a'
As you can see in the last example, we got an error since the positional arguments passed as a tuple are considered first by the python interpreter causing a re-assignment of the argument
All this is quite simple, but I have to admit then when approaching to python and django the first times (and coming from a PHP background) such
**kwargs were something mysterious to me.