Мелкая копия в 1-D списке против 2-D списка - PullRequest
0 голосов
/ 19 сентября 2018

Я нашел много обсуждений, связанных с "мелкой копией" в Python, но я не могу найти свою точную проблему.

Насколько я понимаю, создание мелкой копии все еще содержит ссылки на исходные значения списка,Это справедливо в следующем случае двумерного списка.

>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> y = list(x)
>>> x.append(['New value'])
>>> x
[[1, 2, 3], [4, 5, 6], [7, 8, 9], ['New value']]
>>> y
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> x[0][0] = 'A'
>>> x
[['A', 2, 3], [4, 5, 6], [7, 8, 9], ['New value']]
>>> y
[['A', 2, 3], [4, 5, 6], [7, 8, 9]]

Теперь, в одномерном списке, я не нашел этого эффекта.

>>> a = [1,2,3,4,5]
>>> b = list(a)
>>> a.append(10)
>>> a
[1, 2, 3, 4, 5, 10]
>>> b
>>> [1, 2, 3, 4, 5]
>>> a[0] = 'A'
>>> a
['A', 2, 3, 4, 5, 10]
>>> b
[1, 2, 3, 4, 5]

Может кто-нибудь пожалуйстауточнить, что стоит за этой разницей?

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Мелкая копия копирует элементы верхнего уровня, создавая новый экземпляр каждого.Если есть какие-либо сложные элементы, мелкая копия создаст новую копию этих элементов, но не создаст новые экземпляры их элементов.Ссылки на вложенные списки будут новыми, но ссылки второго уровня будут по-прежнему относиться к исходным объектам.

Глубокая копия создает новый экземпляр каждого элемента в каждый уровень.Одним из побочных эффектов является то, что это удваивает объем памяти, занимаемый этим элементом (теперь два элемента).

Здесь вы можете увидеть эффект крупным планом.Мелкая копия b имеет собственную копию каждого элемента верхнего уровня;когда мы меняем a[0], скаляр, копия в b не меняется.Тогда, хотя b[2] находится в месте, отличном от a[2], значения указателя идентичны: они указывают на один и тот же список нижнего уровня.Таким образом, когда мы изменяем a[2][1], это изменение отражается в b[2][1].

>>> a = [1, 2, ['a', 'b', 'c'], 4, 5]
>>> b = list(a)
>>> a[0] = "new 1"
>>> a[2][1] = "Deeper"
>>> a
['new 1', 2, ['a', 'Deeper', 'c'], 4, 5]
>>> b
[1, 2, ['a', 'Deeper', 'c'], 4, 5]
0 голосов
/ 19 сентября 2018

Thiking с C указателями.В вашем списке много адресов, которые включают в себя список.Вы копируете только новый экземпляр всего списка, но если вы измените содержимое по адресу, который включен в ваш список, это повлияет на этот список. Вы 3 три списка внутри x и внутри y имеют один и тот же адрес, но x и y имеют разные адреса.

x == 0x0123  #Hexadecimal addresses
y == 0x0456
x = [0x01, 0x02, 0x03, whatever_you_want]
y = [0x01, 0x02, 0x03]
0x01 = [1, 2, 3]

Когда мы просто назначаем список вместе, если вместоy = list(x) вы написали y = x, x и y будут изменены одновременно, потому что они будут указывать на один и тот же адрес, как x = y = 0x0123.

Я не совсем уверен во всем, но это то, как я могу понять это с моими фактическими знаниями в C

0 голосов
/ 19 сентября 2018

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

...