Я определю a = [[1,1],[2,2],[3,3]]
немного по-другому. Скажем:
b = [1,1]
c = [2,2]
d = [3,3]
a = [b,c,d]
Это то же самое, что и у вас, мы просто дали имена внутреннему списку, чтобы потом было легче следовать.
Можно назвать эти имена ссылки или указатели на места памяти. Если вы не знакомы с этими терминами, посмотрите на "b
не содержит [1,1]
, он просто знает, где находится в памяти программы" .
Хорошо, теперь на self.a[0] = self.a[1]
. Эта строка говорит программе: «назначить первый элемент списка a таким же, как второй» * . не скажет " скопировать второй элемент в первый" . Разница в том, что и self.a[0]
и self.a[1]
указывают на тот же массив [2,2]
. Другими словами a = [c,c,d]
сейчас.
self.a[1] = self.a[2]
делает то же самое, но для разных элементов, поэтому a = [c, d, d]
. Пока что все так, как вы ожидаете. Массив равен [[2,2],[3,3],[3,3]]
, когда вы его печатаете, но проблема в том, что [3,3]
здесь тот же массив, к нему можно просто получить доступ двумя элементами self.a
.
Теперь давайте рассмотрим self.a[2][0] += 1
шаг за шагом:
- путем вызова
self.a[2]
мы получаем доступ к указателю к массиву d = [3,3]
- после этой логики c, высказывание
self.a[2][0]
- это то же самое, что выражение d[0]
- , поскольку мы увеличили
d[0]
, и оба self.a[1]
и self[2]
указывают до d
, оба self.a[1][0]
и self.a[2][0]
изменились.
Другой способ взглянуть на это состоит в том, что ваш код эквивалентен:
class A():
def __init__(self):
self.b = [1,1]
self.c = [2,2]
self.d = [3,3]
self.a = [self.b, self.c, self.d]
self.a[0] = self.c
self.a[1] = self.d
self.d[0] += 1
print(self.a)
aaa = A()
Массив в self.a
не является массивом который содержит массивы, это просто массив, содержащий переменных, которые знают, где находятся эти массивы (т.е. указатели или ссылки).