1. 程式人生 > 其它 >python程式設計中的小問題彙總

python程式設計中的小問題彙總

技術標籤:pythonpython

前言

本文記錄了我在python程式設計中遇到的各種小問題,持續更新。

1. x = x + 1 VS x += 1

辨析下面這兩段程式碼:

>>> x = y = [1, 2, 3, 4]
>>> x += [4]
>>> x
[1, 2, 3, 4, 4]
>>> y
[1, 2, 3, 4, 4]
>>> x = y = [1, 2, 3, 4]
>>> x = x + [4]
>>> x
[1, 2, 3, 4, 4]
>>> y
[1, 2, 3, 4]

1)'+=' 呼叫in-place的加法,即iadd方法。 此方法採用兩個引數,但是原地進行更改,修改了第一個引數的內容(即x被修改)。 由於x和y都指向相同的Pyobject,因此它們都是相同的。

2)x = x + [4] 呼叫 add 方法,相當於x.add([4]),並沒有原地進行更改或新增值,它會建立一個新列表[1, 2, 3, 4, 4],該列表指向了x,而y仍指向舊列表[1, 2, 3, 4],因此它們不相同。

2. np.matmul(@) VS np.dot VS np.multiply(*)

np.matmul(a, b)是矩陣乘法,運算子過載為@;np.dot(a, b)

是點積;np.multiply(a, b)是逐元素乘法,運算子過載為*

關於三者的辨析,直接上結論:

1)如果a或者b有一個是標量,用np.multiply()或者*,np.dot()可以但不推薦,np.matmul()不可以;

2)如果a、b是向量,則使用np.dot()向量內積;

3)如果a、b是二維array(矩陣),則使用np.matmul()矩陣乘法;

4)a、b是二維及以下array的情況下,np.matmul()np.dot()效果相同;

5)a、b是大於二維array的情況下,如下例:

a = np.array([i for i in range(120)]).reshape([2,3,4,5])
b = np.array([i for i in range(120)]).reshape([2,3,5,4])
>>> np.matmul(a,b).shape
(2, 3, 4, 4)

>>> np.dot(a,b).shape
(2, 3, 4, 2, 3, 4)

>>> np.matmul(b,a).shape
(2, 3, 5, 5)

>>> np.dot(a,b).shape
(2, 3, 5, 2, 3, 5)

重點是觀察結果的維度不同,np.matmul(a,b)的維度為(2, 3, 4, 4),np.dot(a,b)的維度為(2, 3, 4, 2, 3, 4),這是因為np.matmul()遵循了矩陣乘法的維度規則(n,k),(k,m)->(n,m),a的最後一個維度5和b的倒數第二個維度5消掉。

具體的運算,用一個簡單點的例子說明:

a = np.array([i for i in range(12)]).reshape([2,2,3])
b = np.array([i for i in range(12)]).reshape([2,3,2])
"""
a
[[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]]
b
[[[ 0  1]
  [ 2  3]
  [ 4  5]]

 [[ 6  7]
  [ 8  9]
  [10 11]]]
"""

>>> np.matmul(a,b)
array([[[ 10,  13],
        [ 28,  40]],

       [[172, 193],
        [244, 274]]])

>>> np.dot(a,b)
array([[[[ 10,  13],
         [ 28,  31]],

        [[ 28,  40],
         [100, 112]]],


       [[[ 46,  67],
         [172, 193]],

        [[ 64,  94],
         [244, 274]]]])

np.matmul看作是矩陣\begin{bmatrix} 0& 1 &2 \\ 3& 4 &5 \end{bmatrix}\begin{bmatrix} 0 & 1\\ 2& 3\\ 4& 5 \end{bmatrix}相乘得到\begin{bmatrix} 10 &13 \\ 28&40 \end{bmatrix}\begin{bmatrix} 6& 7 &8 \\ 9& 10 &11 \end{bmatrix}\begin{bmatrix} 6 & 7\\ 8& 9\\ 10& 11 \end{bmatrix}相乘得到\begin{bmatrix} 172 &193 \\ 244&274 \end{bmatrix}

np.dot看作是a的最後一個維度的向量\begin{bmatrix} 0\\ 1 \\ 2 \end{bmatrix}\begin{bmatrix} 3\\ 4 \\ 5 \end{bmatrix}\begin{bmatrix} 6\\ 7 \\ 8 \end{bmatrix}\begin{bmatrix} 9\\ 10 \\ 11 \end{bmatrix}與 b的倒數第二個維度的向量\begin{bmatrix} 0\\ 2 \\ 4 \end{bmatrix}分別作內積,得到10、13、28、31即為矩陣\begin{bmatrix} 10 &13 \\ 28&31 \end{bmatrix},再與\begin{bmatrix} 1\\ 3 \\ 5\end{bmatrix}\begin{bmatrix} 6\\ 8 \\ 10 \end{bmatrix}\begin{bmatrix} 7\\ 9 \\ 11 \end{bmatrix}作內積可以得到其他三個矩陣。