@MaxxxZ

В чём ошибка определения переменной экземпляра?

Доброго времени суток!

Есть простенькая программа:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
		
		
g = [[Point(0, 0)] * 7] * 11

deb = open("R:\\debug.txt", "w")    

for i in range(11):
	for j in range(7):                                 
		g[i][j] = Point(i, j)
		
for i in range(11):
	for j in range(7):
		deb.write(str(i)+"-"+str(j)+" "+str(g[i][j].x)+" "+str(g[i][j].y)+"\r\n")
	
deb.close()

В результате вместо ожидаемого вывода:
0-0 0 0
0-1 0 1
и т.д. получаю:
0-0 10 0
0-1 10 1
0-2 10 2
и т.д.

Почему переменная x ведёт себя как переменная класса (неожиданно), а y - как переменная экземпляра (ожидаемо)?
  • Вопрос задан
  • 68 просмотров
Решения вопроса 2
shurshur
@shurshur
Сисадмин, просто сисадмин...
Рекомендую напечатать id объектов, сразу станет видно проблему:

for i in range(11):
  print (f"`{i} {id(g[i])}")
  for j in range(7):
    print (f"  `{j} {id(g[i][j])}")
    #deb.write(str(i)+"-"+str(j)+" "+str(g[i][j].x)+" "+str(g[i][j].y)+"\r\n")


кусочек вывода
`0 140084785493632
  `0 140084785519824
  `1 140084785520544
  `2 140084785519872
  `3 140084785520016
  `4 140084785520448
  `5 140084785520592
  `6 140084785520112
`1 140084785493632
  `0 140084785519824
  `1 140084785520544
  `2 140084785519872
  `3 140084785520016
  `4 140084785520448
  `5 140084785520592
  `6 140084785520112


Все элементы списка длины 11 по первому индексу ссылаются на один и тот же массив длины 7

Ошибка тут в том, что выражение

some_list * 11

конструирует список из 11 ссылок на один и тот же массив. Который на последней итерации цикла получает x=10 во всех элементах.

Решить можно, например, так:

g = []

for i in range(11):
  g.append([])
  for j in range(7):
    g[i].append(Point(i, j))


В python все объекты передаются по ссылке, и это надо учитывать, а при необходимости копировать их явно.
Ответ написан
Комментировать
@MaxxxZ Автор вопроса
Нашёл ещё более красивый ответ:

g = [[0 for x in range(7)] for y in range(10)]
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы