Присвоение значения элементу среза в Python
Это простой вопрос о том, как Python обрабатывает данные и переменные. Я много экспериментировал и в основном выяснил Python, за исключением того, что это продолжает меня запутывать:
[edit: я разделил и переставил примеры для ясности]
Пример 1:
>>> a = [[1], 2]
>>> a[0:1]
[[1]]
>>> a[0:1] = [[5]]
>>> a
[[5], 2] # The assignment worked.
Пример 2:
>>> a = [[1], 2]
>>> a[0:1][0]
[1]
>>> a[0:1][0] = [5]
>>> a
[[1], 2] # No change?
Пример 3:
>>> a = [[1], 2]
>>> a[0:1][0][0]
1
>>> a[0:1][0][0] = 5
>>> a
[[5], 2] # Why now?
может кто-нибудь объяснить мне, что происходит здесь?
до сих пор ответы, кажется, утверждают, что a[0:1]
возвращает новый список, содержащий ссылку на первый элемент a
. Но я не понимаю, как это объясняет Пример 1.
3 ответов
есть[0:1] возвращает новый массив, который содержит ссылку на массив [1], таким образом, вы в конечном итоге изменяя внутренний массив через справочную звонить.
Почему в первом случае не изменяется [1] массив, который вы присваиваете скопированный внешний массив новый внутренний массив.
нижняя строка-a[0: 1] возвращает копию данных, но внутренние данные не копируются.
мое понимание нарезки возвращает новый объект. То есть возвращаемое значение-это новый список.
следовательно, вы не можете использовать оператор присваивания для изменения значений исходного списка
>>> a = [[1], 2, 3]
>>> k = a[0:2]
>>> id(a)
4299352904
>>> id(k)
4299353552
>>>
>>> id(a)
4299352904
>>> id(a[0:2])
4299352832
еще несколько игр по линиям
>>> k = 5
>>>
>>> id(k)
4298182344
>>> a[0] = [1,2]
>>> a
[[1, 2], 2, 3]
>>> id(a)
4299352904
>>>
[Edit: на второй части вопроса]
>>> a[0:1] = [[5]]
следующие обозначения также обычно называются назначение ломтик Поведение для встроенных списков является атомарным (delete + insert) все происходит за один раз. Я понимаю, что это не разрешено для пользовательской последовательности.
существует три различных операции с индексами, все они переведены на вызовы методов:
-
a[i] = b
=>a.__setitem__(i, b)
-
del a[i]
=>a.__delitem__(i)
-
a[i]
используется как выражение =>a.__getitem__(i)
здесь a
, b
и i
- это выражения, и i
может содержать объектов-фрагментов создано с использованием синтаксиса двоеточия. Например:
>>> class C(object):
... def __setitem__(self, *a):
... print a
...
>>> C()[1] = 0
(1, 0)
>>> C()['foo'] = 0
('foo', 0)
>>> C()['foo':'bar'] = 0
(slice('foo', 'bar', None), 0)
>>> C()['foo':'bar',5] = 0
((slice('foo', 'bar', None), 5), 0)
Итак, что происходит в третий пример:
a[0:1][0][0] = 5
становится
a.__getitem__(slice(0,1)).__getitem__(0).__setitem__(0, 5)
первый __getitem__
возвращает копию части списка, а второй __getitem__
возвращает фактический список внутри этого, который затем изменяется с помощью __setitem__
.
ваш второй пример с другой стороны становится
a.__getitem__(slice(0,1)).__setitem__(0, 5)
так __setitem__
вызывается на нарезанной копии, оставляя исходный список нетронутым.