Using *args (reloaded)

I had already written a post on using the asterisk operator [ splat operator anyone ? ] and the double asterisk operator. The problem was, my understanding of the concept wasn’t too clear. Here goes another attempt at it.

Asterisk operator ( * ) can be used in two ways.

1. Getting variable number of arguments into a function

Scenario : You are writing a simple function to chain together arbitrary number of lists to form a single list (by the way itertools.chain does exactly this, but returns a iterator instead). Here, you do not know in advance how many parameters are going to be passed.

def chain(*args):
    result = []
    for arg in args:
        result.extend(arg)
    return result


In  : chain([1,2,3], [4,5,6])
Out : [1,2,3,4,5,6]

What happens here is, all the arguments passed are wrapped into a tuple – args in our case. Now all we need to do is take out the arguments one by one from that tuple, using the loop and adding it to our result list.

2. Unpacking argument lists

In this case, if our arguments are wrapped up in a list or a tuple – the asterisk operator can be used to unpack them.

Scenario : You have a nested list and want to find the sum of each position in lists and create a new list. Add 1st element of list 1, list 2 and list 3, Add 2nd element and so on. [[1,2,3],[4,5,6],[7,8,9]] should provide output as [12,15,18]

To tackle this, we use the zip function, it creates tuples of elements from each corresponding position of the list.


In : zip([1,2,3],[4,5,6])
Out : [(1, 4), (2, 5), (3, 6)]

Clearly, zip takes a number of lists, not a nested list. But our input is a nested list. Asterisk operator to the rescue! . We can use the asterisk operator to unpack our nested list.

def inner_sum(nested_list):
    result = []
    for tup in zip(*nested_list):
        result.append(sum(tup))
    return result

In  : inner_sum([[1,2,3],[4,5,6],[7,8,9]])
Out : [12, 15, 18]

Fun fun fun

Scenario: Transposing a matrix ( essentially a nested list ). A very concise solution would be to use zip with asterisk operator, along with a list comprehension.


In  : matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In  : [ list(x) for x in zip(*matrix) ]
Out : [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

This is similar to how we worked out the inner_sum function, except that we create a new list out of a tuple.

Hopefully that clears up the asterisk operator’s usage.

Standard

Using *args and **kwargs in python

please read the update to this post : Using *args, reloaded!

So we’ve been actively working on our latest project in django – and I came across this weird syntax in views
def view_function(request, *args, **kwargs)

Digging in further, I found that *args stands for argument list, and **kwargs stands for keyword argument list ( well, only the asterik and double asterik matters, the names can be anything ). So, why is this useful again?

For example:

def foo(*args):
  for i, arg in enumerate(*args):
    print "Argument ", i, " : ", arg

and call it by

foo("a", "b", "c")

Simply put, we now have a way to call a function with arbitrary number of parameter. The function foo can be passed with any number of arguments.

So, that’s about *args. Now what is **kwargs? It is the keyword argument list – which means you can pass the keywords as well as their values as a dictionary.

For example:


class Foo(object):
  def __init__(self, value):
    print value

class DerivedFoo(Foo):
  def __init__(self, *args, **kwargs):
    print 'DerivedFoo'
    super(DerivedFoo, self).__init__(*args, **kwargs)

myFoo = DerivedFoo("Calling Foo through DerivedFoo")

The super keyword can be used to call the methods of superclass – in this case the init of class Foo. The parameters which are passed to inherited class can be passed to the base class as shown above. This can be used to extend the behavior of the base class, without knowing anything about base class.

Standard