Функция Python не должна изменять глобальную переменную
Я довольно новичок в Python и Numpy, и я столкнулся с этой проблемой при переводе программы MATLAB на Python.
Насколько я могу судить, приведенный ниже код ведет себя ненормально, изменяя глобальную переменную, даже если это не так.
import numpy as np
A = np.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
def function(B):
B[1,1] = B[1,1] / 2
return B
C = function(A)
print(A)
Выход:
[[0 1 2]
[3 2 5]
[6 7 8]]
Функция делит среднее число матрицы на два и возвращает его. Но, похоже, это также изменяет глобальную переменную.
Здесь можно легко избежать этой проблемы, но я пытаюсь понять, почему она возникает.
По некоторым причинам этого не происходит, если функция делит ВЕСЬ матрицу на 2.
import numpy as np
A = np.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
def function(B):
B = B / 2
return B
C = function(A)
print(A)
Выход:
[[0 1 2]
[3 4 5]
[6 7 8]]
3 ответа
В первом случае
def function(B):
B[1,1] = B[1,1] / 2
return B
Вы изменяете содержимое определенного элемента изменяемого объекта, на который указывает имя B
, Как описано в предыдущем ответе уже.
Принимая во внимание, что в
def function(B):
B = B / 2
return B
Дело в том, что B / 2
это новый объект в целом. Объект, указанный в качестве входных данных, не изменяется.
Тот факт, что вы переназначаете его на местное имя B
неважно. Это делает B
больше не указывает на оригинальный объект, предоставленный в качестве входных данных для функции, но на совершенно новый экземпляр объекта. Эта функция возвращает.
Итак, правильно, экземпляр объекта, на который указывает имя A
не изменяется, даже если он изменчив.
В отличие от MATLAB, Python является pass by reference
язык. Обычно функция получает ссылку на каждый из аргументов. Если функция изменяет аргумент, например, B[1,1]=...
изменение отражается в аргументе.
http://www.mathworks.com/matlabcentral/answers/152-can-matlab-pass-by-reference- это объяснение различия между MATLAB между передачей аргументов по дескриптору v. по значению. По сути, Python/numpy проходит по дескриптору.
Согласно этому ответу, B(1,1) = B(1,1)/2
в MATLAB заставит копию, так что B
больше не делится ссылкой с A
, В Python
такое действие изменяет вызывающий аргумент, не делая копию. То, что это происходит внутри функции, не имеет значения.
Когда у тебя есть B[1,1] = B[1,1]/2
Вы модифицируете элемент изменяемой структуры данных, который изменяет структуру данных. В B = B / 2
Вы переназначаете B в локальной области, чтобы указать на что-то еще. Это изменение не сохраняется при выходе из локальной области.