Book Image

Practical Maya Programming with Python

By : Robert Galanakis
Book Image

Practical Maya Programming with Python

By: Robert Galanakis

Overview of this book

Table of Contents (17 chapters)
Practical Maya Programming with Python
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

The args and kwargs parameters


We frequently use functions and methods with asterisk or star characters (*) in their definitions, as shown in the following code snippet:

def spam(*args, **kwargs):
    ...

Programmers unfamiliar with Python are often puzzled when they encounter this for the first time. What does the single and double asterisk/star character do?

We'll start with *args. The single * character tells Python that the function takes a variable number (zero or more) of positional parameters.

>>> def countargs(*args):
...     print 'Passed in', len(args), 'args.'
>>> countargs('a', 'b', 'c')
Passed in 3 args.
>>> countargs()
Passed in 0 args.

You can combine normal positional parameters and *args to require some arguments. The os.path.join method, for example, requires at least one positional argument. Its signature is os.path.join(a, *p).

>>> import os
>>> os.path.join('a', 'b', 'c')
'a\\b\\c'
>>> os.path.join('a')
'a'
>>> os.path.join()
Traceback (most recent call last):
TypeError: join() takes at least 1 argument (0 given)

In the last call to os.path.join, we did not supply any arguments, so a TypeError was raised.

You can also use the * character when calling a function to expand a sequence (such as a list or tuple) into positional arguments. This does not require the function being called has a *args parameter. It can be used to expand to any positional arguments. For example, if we use the countargs function defined previously with a list of values, we will get two very different results depending on whether we use a * to expand the list when countargs is called.

>>> items = ['a', 'b', 'c']
>>> countargs(items)
Passed in 1 args.
>>> countargs(*items)
Passed in 3 args.

The first call to countargs would be equivalent to countargs(['a', 'b', 'c']). It passes the list as the only argument. The second call would be equivalent to countargs('a', 'b', 'c'). It passes each item in the list as a separate positional argument.

The **kwargs parameter is basically the same as *args, but for keyword instead of positional parameters. The ** characters tell Python a function takes a variable number of keyword parameters.

>>> def countkwargs(**kwargs):
...     print 'Passed in', len(kwargs), 'kwargs.'
>>> countkwargs(a=1, b=2)
Passed in 2 kwargs.
>>> countkwargs()
Passed in 0 kwargs.

Just like you can specify both required and variable positional parameters (as we saw in os.path.join), you can specify regular keyword parameters along with using **kwargs.

>>> def countkwargs2(strfunc=None, **kwargs):
...     msg = 'Passed in %s kwargs.' % len(kwargs)
...     if strfunc:
...         msg = strfunc(msg)
...     print msg
>>> countkwargs2(strfunc=str.upper, a=1)
PASSED IN 1 KWARGS.
>>> countkwargs2(str.lower, a=1, b=2)
passed in 2 kwargs.

As the second call to countkwargs2 shows, you can still use normal keyword arguments by either position or name.

And finally, you can use ** to expand a mapping, such as a dictionary, into keyword arguments that are passed into a function:

>>> mapping = dict(a=1, b=2, strfunc=str.upper)
>>> countkwargs2(arg=mapping)
Passed in 1 kwargs.
>>> countkwargs2(**mapping)
PASSED IN 2 KWARGS.

The *args and **kwargs parameters are important features of Python with many useful applications, just a fraction of which are presented in this book. They allow a level of dynamic programming that would otherwise be extremely difficult.

As a final note, the names args and kwargs are convention only. You can just as well name them *spam and **eggs.