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

StackOverflow https://stackoverflow.com/questions/323689

  •  11-07-2019
  •  | 
  •  

Вопрос

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

newList = oldList[:]

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

newList = oldList

Или я что-то упускаю?

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

>>> 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]

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

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

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

Изменчивость также является причиной того, что это:

def myfunction(mylist=[]): 
    pass

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

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

См. также модуль копирования: & nbsp; http://docs.python.org/ библиотека / copy.html

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

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']
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top