In [40]: X = np.arange(10).reshape(5,2)
Используя outer
и список / карту из принятого ответа:
In [41]: outer = lambda V: np.array([[x*x1 for x in V] for x1 in V])
In [43]: list(map(outer, X))
Out[43]:
[array([[0, 0],
[0, 1]]),
array([[4, 6],
[6, 9]]),
array([[16, 20],
[20, 25]]),
array([[36, 42],
[42, 49]]),
array([[64, 72],
[72, 81]])]
Используя numpy
широковещательную рассылку:
In [44]: X[:,:,None]*X[:,None,:]
Out[44]:
array([[[ 0, 0],
[ 0, 1]],
[[ 4, 6],
[ 6, 9]],
[[16, 20],
[20, 25]],
[[36, 42],
[42, 49]],
[[64, 72],
[72, 81]]])
Для (5,2 ) X
результат представляет собой массив (5,2,2).
Некоторые небольшие временные тесты:
In [55]: timeit list(map(outer, X))
51.8 µs ± 1.29 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [57]: timeit [outer(i) for i in X]
49.8 µs ± 65.9 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [58]: timeit X[:,:,None]*X[:,None,:]
5.37 µs ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
list/map
имеет примерно такую же скорость, как и понимание списка. В общем, я считаю, что понимание списка более четкое. Но широковещательные операции numpy обычно выполняются намного быстрее.
Если вы собираетесь выполнять итерацию, подумайте о работе со списками; обычно быстрее:
In [61]: timeit [outer(i) for i in X.tolist()]
24.3 µs ± 63.6 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [62]: outer0 = lambda V: [[x*x1 for x in V] for x1 in V]
In [64]: timeit [outer0(i) for i in X.tolist()]
7.33 µs ± 16 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)