Pythonic way will be to use itertools.product
, as it returns Cartesian product of the iterables passed to it. As no Python loop is involved it is going to be fast compared to version that are using loop:
>>> from operator import sub
>>> from itertools import starmap, product
>>> list(starmap(sub, product(a, b)))
[-3, -4, -5, -2, -3, -4, -1, -2, -3]
In NumPy you can do this using the recipes mentioned here:
>>> arr = np.dstack(np.meshgrid(a, b)).reshape(-1, 2)
>>> np.subtract(arr[:,0], arr[:,1])
array([-3, -2, -1, -4, -3, -2, -5, -4, -3])
Timing comparisons:
>>> b = [4, 5, 6]*1000
>>> a = [1, 2, 3]*1000
>>> %timeit list(starmap(sub, product(a, b)))
1 loops, best of 3: 464 ms per loop
>>> %timeit [x - y for x in a for y in b]
1 loops, best of 3: 491 ms per loop
>>> %%timeit
result = []
for x in a:
for y in b:
result.append(x - y) #attribute lookup is slow
...
1 loops, best of 3: 908 ms per loop
>>> %%timeit
result = [];append = result.append
for x in a:
for y in b:
append(x - y)
...
1 loops, best of 3: 617 ms per loop
#Numpy version will be little faster if a and b were nd arrays.
>>> %timeit arr = np.dstack(np.meshgrid(a, b)).reshape(-1, 2);np.subtract(arr[:,0], arr[:,1])
1 loops, best of 3: 573 ms per loop