1. 程式人生 > >python中函式引數的引用與傳值

python中函式引數的引用與傳值

最近自己寫了個函式,實現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

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):
            #一次順時針旋轉90matrix[:] = 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,因此也會另外開闢地址儲存資料。