python程式設計中的小問題彙總
前言
本文記錄了我在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)
關於三者的辨析,直接上結論:
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看作是矩陣與相乘得到,與相乘得到;
np.dot看作是a的最後一個維度的向量、、、與 b的倒數第二個維度的向量分別作內積,得到10、13、28、31即為矩陣,再與、、作內積可以得到其他三個矩陣。