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