Python 2.6 автоматически превращает переменные внутри определения функции в определенные условия? Зачем? - PullRequest
1 голос
/ 21 апреля 2011

Я совершенно ошеломлен, почему происходит следующее:

Вот мой код:


def add_one(array):

    new_array = array
    length = len(array)

    for i in range(length):

        new_array[i] = new_array[i]+1


    return new_array

x = [1,2,3,4,5];
y = add_one(x)

print x

print y

Вот результаты:

[2, 3, 4, 5, 6]

[2, 3, 4, 5, 6]

Я не понимаю, почему х меняется.

Мои размышления: Каким-то образом x передается в качестве глобальной переменной функции add_one. Я включил 'new_array = array', чтобы если массив был глобальной переменной x, x не изменился бы. Однако каким-то образом new_array также стал глобальной переменной x при выполнении 'new_array = array'. Я написал альтернативную версию функции add_one, которая не вызывала у меня проблем:


def add_one(array):

    new_array = []
    length = len(array)

    for i in range(length):
        new_array.append(array[i]+1)

Кажется, что если локальная переменная (то есть массив) редактируется ее индексом в функции, она становится глобальной по отношению к глобальной переменной, которая была взята в качестве входных данных для этой функции?

Понятия не имею, что происходит. Любые объяснения будут высоко оценены.

Ответы [ 4 ]

6 голосов
/ 21 апреля 2011

Когда вы говорите new_array = array, вы не делаете копию массива, вы просто создаете другое имя для массива.Оба имени по-прежнему применяются к одному и тому же массиву.

Чтобы сделать копию, проще всего использовать нарезку: new_array = array[:]

4 голосов
/ 21 апреля 2011

Ничто не сделано глобальным для непонятных чтений. array - все еще совершенно нормальная локальная переменная. Но это ссылка, так как все в Python (ну, по крайней мере, каждое имя) является ссылкой:

  • add_one(x) передает ссылку (не как ссылку, например, в C ++, скорее как указатель - если что-то из этого что-то значит для вас) на x на add_one
  • new_array = array просто скопирует эту ссылку
  • Копирование не происходит, все эти имена указывают на один и тот же объект!

Это означает, что вызов метода на array в add_one изменил тот же объект, на который ссылается x вызывающей стороны - переназначение array (array = []) просто перезапишет локальную копию ссылаются и не влияют на другие переменные, ссылающиеся на тот же объект (в конце концов, вполне возможно, что такой переменной нет!), но присваивание члена или элемента (например, new_array[i] = ...) в основном является вызовом метода, а будет изменить объект.

Как правило, самый простой способ создать новый список из существующего с некоторым шаблоном модификации, примененным к каждому элементу и, при желании, некоторой фильтрацией, использует понимание списка. [x + 1 for x array] в этом примере.

1 голос
/ 21 апреля 2011

В третьей строке вы установили y на x.

new_array = array
0 голосов
/ 21 апреля 2011

Эта строка является ключевой:

new_array = array

Вы должны видеть new_array не как новую переменную, а как новое имя переменной (объекта), которая уже имеет имя array.

...