Подтвердить что ты не робот

Синтаксис фрагмента списка Python, используемый без видимой причины

Я иногда вижу синтаксис списка списка, используемый в коде Python следующим образом:

newList = oldList[:]

Конечно, это то же самое, что:

newList = oldList

Или я что-то не хватает?

4b9b3361

Ответ 1

Как и NXC, имена переменных Python фактически указывают на объект, а не на определенное место в памяти.

newList = oldList создаст две разные переменные, которые указывают на один и тот же объект, поэтому изменение oldList также изменит newList.

Однако, когда вы делаете newList = oldList[:], он "разрезает" список и создает новый список. Значения по умолчанию для [:] равны 0 и концу списка, поэтому он копирует все. Поэтому он создает новый список со всеми данными, содержащимися в первом, но оба могут быть изменены без изменения другого.

Ответ 2

[:] Мелкие копии списка, создавая копию структуры списка, содержащей ссылки на исходные элементы списка. Это означает, что операции с копией не влияют на структуру оригинала. Однако, если вы что-то делаете с членами списка, оба списка по-прежнему относятся к ним, поэтому обновления будут отображаться, если к элементам будет доступ через оригинал.

A Deep Copy также сделает копии всех членов списка.

В приведенном ниже фрагменте кода показана мелкая копия в действии.

# ================================================================
# === ShallowCopy.py =============================================
# ================================================================
#
class Foo:
    def __init__(self, data):
        self._data = data

aa = Foo ('aaa')
bb = Foo ('bbb')

# The initial list has two elements containing 'aaa' and 'bbb'
OldList = [aa,bb]
print OldList[0]._data

# The shallow copy makes a new list pointing to the old elements
NewList = OldList[:]
print NewList[0]._data

# Updating one of the elements through the new list sees the
# change reflected when you access that element through the
# old list.
NewList[0]._data = 'xxx'
print OldList[0]._data

# Updating the new list to point to something new is not reflected
# in the old list.
NewList[0] = Foo ('ccc')
print NewList[0]._data
print OldList[0]._data

Запуск в оболочке python дает следующую расшифровку. Мы можем видеть список делается с копиями старых объектов. Один из объектов может иметь его состояние обновляется по ссылке через старый список, а обновления могут быть когда объект просматривается через старый список. Наконец, изменение ссылка в новом списке, как видно, не отражена в старом списке, поскольку новый список теперь относится к другому объекту.

>>> # ================================================================
... # === ShallowCopy.py =============================================
... # ================================================================
... #
... class Foo:
...     def __init__(self, data):
...         self._data = data
...
>>> aa = Foo ('aaa')
>>> bb = Foo ('bbb')
>>>
>>> # The initial list has two elements containing 'aaa' and 'bbb'
... OldList = [aa,bb]
>>> print OldList[0]._data
aaa
>>>
>>> # The shallow copy makes a new list pointing to the old elements
... NewList = OldList[:]
>>> print NewList[0]._data
aaa
>>>
>>> # Updating one of the elements through the new list sees the
... # change reflected when you access that element through the
... # old list.
... NewList[0]._data = 'xxx'
>>> print OldList[0]._data
xxx
>>>
>>> # Updating the new list to point to something new is not reflected
... # in the old list.
... NewList[0] = Foo ('ccc')
>>> print NewList[0]._data
ccc
>>> print OldList[0]._data
xxx

Ответ 3

Как уже было сказано, я просто добавлю простую демонстрацию:

>>> a = [1, 2, 3, 4]
>>> b = a
>>> c = a[:]
>>> b[2] = 10
>>> c[3] = 20
>>> a
[1, 2, 10, 4]
>>> b
[1, 2, 10, 4]
>>> c
[1, 2, 3, 20]

Ответ 4

Никогда не думайте, что "a = b" в Python означает "копировать b в a". Если с обеих сторон есть переменные, вы не можете этого знать. Вместо этого подумайте об этом как "дайте b дополнительное имя a".

Если b - неизменяемый объект (например, число, кортеж или строка), то да, эффект заключается в том, что вы получаете копию. Но это потому, что, когда вы имеете дело с неизменяемыми (что, возможно, должно было быть названо только для чтения, неизменным или WORM), вы всегда получаете копию по определению.

Если b является изменчивым, вы всегда должны сделать что-то дополнительное, чтобы убедиться, что у вас есть подлинная копия. Всегда. Со списками это так же просто, как срез: a = b [:].

Мутация также является причиной того, что это:

def myfunction(mylist=[]): 
    pass

... не совсем делает то, что вы думаете.

Если вы из C-фона: то, что осталось от "=", является указателем, всегда. Все переменные - указатели, всегда. Если вы поместите переменные в список: a = [b, c], вы указали указатели на значения, на которые указывают b и c в списке, на который указывает a. Если вы затем установите [0] = d, указатель в позиции 0 теперь указывает на то, что d указывает на.

См. также модуль-копия: http://docs.python.org/library/copy.html

Ответ 5

Неверная копия: (копирует куски памяти из одного места в другое)

a = ['one','two','three']

b = a[:]

b[1] = 2

print id(a), a #Output: 1077248300 ['one', 'two', 'three']
print id(b), b #Output: 1077248908 ['one', 2, 'three']

Deep Copy: (копирует ссылку на объект)

a = ['one','two','three']

b = a

b[1] = 2


print id(a), a #Output: 1077248300 ['one', 2, 'three']
print id(b), b #Output: 1077248300 ['one', 2, 'three']