How to pack the elements of product of matrix multiplication back
Question: A beginner to Python, I am trying to work my way into understanding how to do
things in as Pythonic a way as possible.

I am attempting to write a function to which returns result of matrix
multiplication of 2 matrices. here's what I came up with:

    
    
     def matmul(a,b):
         c = zip(*b)
         def element(i,j):
             return reduce(lambda x,y: x+y,map(lambda x:x[0]*x[1],zip(a[i],c[j])))
         print [element(i,j) for i in range(len(a)) for j in range(len(c))]
    

The list that I am printing contains the product of each element of the
product, but it's a list not a matrix.

    
    
    >>> a = [[1,2],[3,4]]
    >>> b = [[1,1],[1,1]]
    >>> matmul(a,b)
    [3, 3, 7, 7] 
    >>> a = [[1,1,1],[2,2,2],[3,3,3]]
    >>> b = [[1,8,7],[8,7,11],[7,8,2]]
    >>> matmul(a,b)
    [16, 23, 20, 32, 46, 40, 48, 69, 60]
    

`[3,3,7,7]` should be actually be represented as `[[3,3],[7,7]]` and `[16, 23,
20, 32, 46, 40, 48, 69, 60]` as `[[16, 23, 20],[32, 46, 40],[48, 69, 60]]`

But, I am not able to think of a concise way to pack the list back into 2D.

How would I easily and concisely go about doing so ?


Answer: You were very close, you just need to use a nested list-comprehension with
`zip(*)`:

    
    
    zip(*[[element(i,j) for i in range(len(a))] for j in range(len(c))])
    

A re-factored version of your code:

    
    
    from operator import mul
    from itertools import starmap, izip, imap
    
    def matmul(a, b):
         c = zip(*b)
         def element(row):
             # or   [sum(map(mul, row, col)) for col in c]  
             # or   [sum(imap(mul, row, col)) for col in c]  
             return [sum(starmap(mul, izip(row, col))) for col in c]
         print [element(row) for row in a]
    

* * *

Most concise way will be use
[`numpy.matrix`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html):

    
    
    >>> import numpy as np
    >>> a = np.matrix([[1,2],[3,4]])
    >>> b = np.matrix([[1,1],[1,1]])
    >>> a * b
    matrix([[3, 3],
            [7, 7]])
    

* * *

In Python 3.5(not released yet) we will be able to use the `@` operator on
Python lists to do [matrix
multiplications](http://legacy.python.org/dev/peps/pep-0465/).

