Python, когда использовать copy.copy

Я думаю, что начинаю понимать питон, но у меня все еще есть проблемы с основным вопросом. Когда использовать copy.copy?

>>>a=5
>>>b=a
>>>a=6
>>>print b
5

Хорошо имеет смысл. Но в каких обстоятельствах выражение b=a образует какую-то "связь" между a и b, так что модификация a затем изменит b? Это то, о чем я не могу сказать о copy.copy - каждый раз, когда вы назначаете одну переменную другой, знак равенства просто копирует значение?

Ответ 1

В принципе, b = a указывает b туда, где a указывает, и ничего больше.

То, о чем вы спрашиваете, является изменяемым типом. Числа, строки, кортежи, фризонеты, булевы, None, неизменяемы. Списки, словари, наборы, bytearrays, являются изменяемыми.

Если я создаю изменяемый тип, например list:

>>> a = [1, 2]  # create an object in memory that points to 1 and 2, and point a at it
>>> b = a       # point b to wherever a points
>>> a[0] = 2    # change the object that a points to by pointing its first item at 2
>>> a
[2, 2]
>>> b
[2, 2]

Они оба будут указывать на один и тот же элемент.

Я также прокомментирую ваш исходный код:

>>>a=5     # '5' is interned, so it already exists, point a at it in memory
>>>b=a     # point b to wherever a points
>>>a=6     # '6' already exists in memory, point a at it
>>>print b # b still points at 5 because you never moved it
5

Вы всегда можете видеть, где что-то указывает на память, делая id(something).

>>> id(5)
77519368
>>> a = 5
>>> id(a)
77519368     # the same as what id(5) showed us, 5 is interned
>>> b = a
>>> id(b)
77519368     # same again
>>> id(6)
77519356
>>> a = 6
>>> id(a)
77519356     # same as what id(6) showed us, 6 is interned
>>> id(b)
77519368     # still pointing at 5.    
>>> b
5

Вы используете copy, когда хотите сделать копию структуры. Тем не менее, не сделает копию интернированного. Это включает в себя целые числа меньше 256, True, False, None, короткие строки, такие как a. В принципе, вы должны почти никогда не использовать его, если не уверены, что не будете запутаны в процессе интернирования.

Рассмотрим еще один пример, который показывает даже с изменяемыми типами, указывая одну переменную на что-то новое, но не меняет старую переменную:

>>> a = [1, 2]
>>> b = a
>>> a = a[:1]    # copy the list a points to, starting with item 2, and point a at it
>>> b            # b still points to the original list
[1, 2]
>>> a
[1]
>>> id(b)
79367984
>>> id(a)
80533904

Нарезка списка (всякий раз, когда вы используете :) делает копию.

Ответ 2

Назначение никогда не копируется. Он просто связывает объект с ссылками a (придерживаться примера) до b. a и b ссылаются на один и тот же объект, пока вы не измените ссылку на него.

Полезно отбрасывать "переменную" как термин, это просто ярлык, который вы помещаете в объект, дескриптор, который вы можете использовать для доступа к объекту, и ничего больше.

copy.copy не изменяет это вообще.

Если вы хотите распространять изменения даже для чисел или строк - здесь отображается неизменяемость - вам нужно обернуть числа и строки в другом объекте и назначить его a и b.

Если вы хотите пойти наоборот, вы должны использовать модуль copy, но обязательно прочитайте документы. Но вы должны думать в терминах объектов не.