Почему python обрабатывает списки подобным образом при определении функции? - PullRequest
0 голосов
/ 01 июня 2018

Я делал код, и переменные стали вести себя странно и были привязаны к вещам, которые, как я думал, не должны были.Итак, я решил свести ситуацию к минимальной сложности, чтобы решить мои сомнения, и вот что произошло:

Следующий код:

a = [2]

def changeA(c):
    d = c
    d[0] = 10
    return True

changeA(a)

print(a)

печатает '[10]'.Это не имеет смысла для меня, так как я никогда не назначал список «а», чтобы быть чем-либо после первого назначения.Внутри функции changeA локальная переменная d назначена входом функции, , и мне кажется, что это назначение происходит в обоих направлениях, и даже меняется "снаружи" .Если так, то почему?Если нет, то почему это происходит?

Я также заметил, что код

a = [2]

def changeA(c):
    d = list(c)
    d[0] = 10
    return True

changeA(a)

print(a)

ведет себя нормально (то есть, как я ожидал).

РЕДАКТИРОВАТЬ:Этот вопрос считается дубликатом этого .Я не думаю, что это правда, так как здесь также важно, чтобы локальный характер процедур внутри функции нарушался.

Ответы [ 6 ]

0 голосов
/ 01 июня 2018

«d = c» означает справочную копию, как указано выше.Это означает, что теперь d будет ссылаться на тот же объект, что и c.Поскольку вы выполняете прямую манипуляцию с объектом, на который ссылается, значение объекта, на которое ссылался a, также изменяется.

Когда вы делаете 'd = list (c)', это означает, что новый списокОбъект создан, запечен в ц.Однако d больше не ссылается на тот же объект, что и a.Следовательно, изменения внутри функции не влияют на.

0 голосов
/ 01 июня 2018

Это потому, что когда вы делаете:

 d = list(c)

, это создает новый объект.Но когда вы делаете

d = c

, вы делаете ссылку на этот объект.

, если вы сделали

d.append(5)

для первого примера, вы получите

[10,5]

То же действие, что и для второго, и список не изменяется.

Более подробное объяснение по следующей ссылке: http://henry.precheur.org/python/copy_list

0 голосов
/ 01 июня 2018

В первом примере вы просто передаете ссылку c (то есть a) на d.

Так что все, что вы делаете для d, произойдет на a.

Во втором примере вы копируете значение c (то есть a) и присваиваете его новой переменной d.

Таким образом, d теперь имеет то же значение, что и c (то есть a), но другую ссылку.

Примечание: вы можете увидеть ссылку или идентификатор переменной, используя функцию id().

a = [2]
print id(a)

def changeA(c):
    d = c
    pirnt id(d)
    d[0] = 10
    return True

changeA(a)

print(a)


a = [2]
print id(a)
def changeA(c):
    d = list(c)
    print id(d)
    d[0] = 10
    return True

changeA(a)

print(a)
0 голосов
/ 01 июня 2018

Переменные Python являются ссылками на объекты, а некоторые объекты являются изменяемыми.Числа не являются, не являются ни строками, ни кортежами, а списками, наборами и кодами.

Давайте посмотрим на следующий код Python

a = [2]       # ok a is a reference to a mutable list
b = a         # b is a reference to the exact same list
b[0] = 12     # changes the value of first element of the unique list
print(a)      # will display [12]
0 голосов
/ 01 июня 2018

В версии 1 вы создаете список a, передаете его функции под псевдонимом c, создаете другой псевдоним d для того же списка, а затем изменяете первыйзначение в этом списке.a, c и d все ссылаются на один и тот же список.

В версии 2 вы используете list(c), что для Python означает "взять содержимое этой итерируемой вещи"с именем c и создайте новый, отличный от него список с именем d ".Теперь есть две копии вашего списка.Один упоминается как a или c, а другой - d.Поэтому при обновлении d[0] вы работаете со второй копией списка.a остается без изменений.

0 голосов
/ 01 июня 2018

В Python имена относятся к значениям, поэтому у вас есть 2 имени, указывающих на одно и то же значение.

...