Неожиданное присвоение внутри функции переменным в пространстве имен в python с использованием + = - PullRequest
1 голос
/ 07 мая 2020

Это чисто методологический вопрос. У меня есть функция basi c, и она неожиданно добавляет значения в список, который я создал. Я знаю, что .append() и .extend() изменяют объект списка на месте, но моя конкретная проблема связана с +=.

У меня создалось впечатление, что x+=y совпадает с x = x+y но это не так в функции, где я обнаружил, что она перезаписывает локальные переменные, определенные внешне для функции.

Позвольте мне проиллюстрировать:

def test1(lst):
    lst += ['new element']
    return 'something else'

def test2(lst):
    lst = lst + ['new element']
    return 'something else'

# Testing them
lst = ['a','sample','list']
test1(lst)
print('test1 returns the following:',lst)

lst = ['a','sample','list']
test2(lst)
print('test2 returns the following:',lst)

Это возвращает

test1 returns the following: ['a', 'sample', 'list', 'new element']
test2 returns the following: ['a', 'sample', 'list']

Конечно, если вы измените имена переменных, то этого не произойдет. Но это в корне меняет мое понимание переменных, определенных внутри функций, а не локально, и может иметь серьезные последствия для моего поведения при кодировании. Может кто-нибудь внятно объяснить, что происходит?

1 Ответ

1 голос
/ 07 мая 2020

Конечно, если вы измените имена переменных, этого не произойдет.

Это неправда. Обратите внимание:

def test1(foo):
    foo += ['new element']

def test2(foo):
    foo = foo + ['new element']

lst = ['a','sample','list']
test2(lst)   # lst stays the same
test1(lst)   # lst gets changed

В обоих случаях мы привязываем foo к списку, иначе известному как lst. В test2 мы назначаем локальному имени foo результат добавления этого списка в список, содержащий 'new element'.

В test1, мы изменяем список на месте, используя += оператор.


У меня создалось впечатление, что x+=y было таким же, как x = x+y

Это неправда, но есть ядро истины в нем: когда __iadd__ не определен для типа x, Python по умолчанию выполняет x = x + y. Кроме того, даже если вы используете только операторы расширенного присваивания (например, +=) внутри функции, компилятор пометит это имя как локальное (STORE / LOAD_FAST).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...