python中函式引數的引用與傳值
阿新 • • 發佈:2019-01-30
最近自己寫了個函式,實現numpy陣列180度旋轉的功能:
import numpy as np
def rotate(matrix):
if matrix.ndim == 2:
matrix = list(matrix)
for i in range(2):
#一次順時針旋轉90度
matrix[:] = map(list,zip(*matrix[::-1]))
return np.array(matrix)
elif matrix.ndim == 3:
for j in range(matrix.shape[0]):
matrix[j] = rotate(matrix[j])
return np.array(matrix)
weights2 = np.array(
[[[2,2,1],
[1,2,1],
[1,2,0]],
[[1,0,1],
[1,1,1],
[1,2,0]],
[[0,0,2],
[1,2,1],
[0,1,1]]])
觀察一下,發現輸出正確,但再次輸出weights2時,發現也跟著旋轉了
很好奇為啥只是作為函式輸入的weights2在函式內部會被修改,後來瞭解到python中可變引數一般是引數引用而不是引數傳值,對於一般的賦值也是如此。
比如:
matrix = weights2
print(weights2)
print(id(weights2),'\n',id(matrix))
matrix[0][0][0] = 10
print(weights2)
發現直接賦值時,兩個變數的ID竟然是相同的,也就是兩個變數完全等價,任意一個變數修改都會影響到另一個。試試下一種賦值方法
matrix = weights2[:]
print(weights2)
print(id(weights2),'\n',id(matrix))
matrix[0][0][0] = 10
print(weights2)
兩個變數不相同,但是變數指向的元素地址卻相同,所以二者還是相關聯的。
再來看一種情況如下:
matrix = weights2[0]
print(weights2)
print(id(weights2),'\n',id(matrix))
matrix[0][0] = 10
print(weights2)
即使只取weights2[0]賦給matrix,但二者還是共享變數地址,因此二者還是相關聯的。
如何避免兩個變數相關聯的情況呢,可以對原來的變數進行一些運算,因為有運算,所以會另外開闢地址儲存運算結果,並將運算結果賦值給左端變數matrix,使得matrix與weights2兩個變數指向的地址不再相同。
matrix = weights2 + 0
print(weights2)
print(id(weights2),'\n',id(matrix))
matrix[0][0][0] = 10
print(weights2)
這次總算實現了對matrix修改,而weights2保持不變了。
最後貼上我對rotate函式的兩種修改:
def rotate(matrix):
if matrix.ndim == 2:
matrix = list(matrix)
for i in range(2):
#一次順時針旋轉90度
matrix[:] = map(list,zip(*matrix[::-1]))
return np.array(matrix)
elif matrix.ndim == 3:
matrix = matrix + 0.0
for j in range(matrix.shape[0]):
matrix[j] = rotate(matrix[j])
return np.array(matrix)
def rotate(matrix):
matrix1 = list(matrix)
if matrix.ndim == 2:
for i in range(2):
#一次順時針旋轉90度
matrix1[:] = map(list,zip(*matrix1[::-1]))
return np.array(matrix1)
elif matrix.ndim == 3:
for j in range(matrix.shape[0]):
matrix1[j] = rotate(matrix1[j])
return np.array(matrix1)
後面一種在開始就對matrix取list,因此也會另外開闢地址儲存資料。