Функция 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 в локальной области, чтобы указать на что-то еще. Это изменение не сохраняется при выходе из локальной области.

Другие вопросы по тегам