Я пишу код, который выполняет матричные операции в функциях, и я использую массивы numpy для хранения моих матриц. Из книг и обсуждений здесь я понял, что скалярные аргументы функций передаются по значению, а массивы передаются способом, похожим на C (в C мы бы сказали, что передается указатель на массив, и эквивалентное действие происходит в Python).
Вот два простых кода на Python, первый из которых успешно умножает 2 матрицы и передает результат обратно в вызываемый код. Я достиг этого, вручную реализовав умножение матриц, следуя подсказке, которую я видел здесь (или на аналогичном форуме). Во втором я заменяю ручное умножение матриц на c=np.dot(a,b), и произведение матриц не передается обратно.
Как заставить работать второй подход?
Пример 1:
import numpy as np
def my_func(a,b,c):
for i in range (0,2):
for j in range (0,2):
c[i,j]=0.
for k in range(0,2):
c[i,j]=c[i,j]+a[i,k]*b[k,j]
print("c")
print(c)
d = np.array([[1,2],[3,4]])
e = np.array([[-1,3],[2,-1]])
f = np.zeros((2,2))
my_func(d,e,f)
print("f")
print(f)
и вот вывод:
c
[[3. 1.]
[5. 5.]]
f
[[3. 1.]
[5. 5.]]
Пример 2:
import numpy as np
def my_func(a,b,c):
c=np.dot(a,b)
print("c")
print(c)
d = np.array([[1,2],[3,4]])
e = np.array([[-1,3],[2,-1]])
f = np.zeros((2,2))
my_func(d,e,f)
print("f")
print(f)
и вот вывод:
c
[[3 1]
[5 5]]
f
[[0. 0.]
[0. 0.]]
Ответ
Для решения вашей проблемы с возвратом результирующей матрицы при использовании функции np.dot
в Python вы должны учитывать, что при присваивании в функции, как в вашем втором примере, переменной c
внутри функции вы фактически создаете новую локальную переменную, а не изменяете элемент f
, который был передан в функцию. Чтобы передать результирующую матрицу обратно, необходимо вернуть значение из функции.
Вот как можно модифицировать ваш второй пример, чтобы он работал так, как задумано:
import numpy as np
def my_func(a, b):
c = np.dot(a, b) # здесь мы создаем новую матрицу c
print("c")
print(c)
return c # возвращаем значение c
d = np.array([[1, 2], [3, 4]])
e = np.array([[-1, 3], [2, -1]])
f = my_func(d, e) # теперь мы вызываем функцию и присваиваем результат переменной f
print("f")
print(f)
Вывод будет следующим:
c
[[3 1]
[5 5]]
f
[[3 1]
[5 5]]
Таким образом, с точки зрения передачи массивов (numpy массивов в вашем случае), когда вы хотите, чтобы изменения, сделанные в функции, были видны вне ее, вы можете либо изменять сам массив, как в вашем первом примере, либо возвращать новый массив, как в исправленном примере второго.
Использование второго подхода (возврат значения) часто более предпочтительно, поскольку это делает функции более чистыми и предсказуемыми.