Странности со списками в Python |
[Nov. 30th, 2008|12:25 pm] |
Тем временем то ли нашёл ещё одну крупную кривизну то ли в Питоне, то ли в собственных руках.
Был мне нужен список списков одинаковых значений. И я его, недолго думая, организовал строчкой:
L = [[1] * 30] * 30]
Но после этого, попытавшись с этим списком работать, я обнаружил, что присваивание 0 какому-то из элементов в строке обнуляет всю строку. Немножко потупив, я догадался, что, скорее всего, дело в питоновском implicit sharing (кстати, что-то я с утра туплю — есть устоявшийся русский термин?), и написал вместо вышеупомянутой строки цикл:
L = []
for i in range(30):
М = []
for j in range(30):
М += [1]
L += [М]
Всё немедленно заработало, конечно. "Но осадочек остался". Как-то, по-моему, это "неаккуратненько"©. А вы как думаете? |
|
|
Comments: |
не должно обнулять строку, должно обнулять столбец. Это и задумано так, умножать mutables в питоне надо осторожно. c = [[1]*30 for i in range(30)] должно быть достаточно.
![[User Picture]](http://lj.rossia.org/userpic/4/5) | From: | yushi |
Date: | November 30th, 2008 - 08:16 pm |
---|
| | | (Link) |
|
не должно обнулять строку, должно обнулять столбец. Это и задумано так
А почему? То есть, зачем нужно implicit sharing вообще, я понимаю. Но как и по каким причинам Питон решает, когда из одной переменной пора делать две разных?
Если лень объяснять, просто дайте ссылку, где про это пишут.
Сколь я помню, implicit sharing всегда (т.е. копирование всегда по ссылке), а две разных создаются, когда эксплицитно вызывается копиконструктор для mutable objects. копиконструктор для immutable возвращает тот же объект. >>> r = (1, 2, 6) >>> r (1, 2, 6) >>> r1 = r >>> r2 = tuple(r) >>> r3 = r[:] >>> id(r), id(r1) , id(r2), id(r3) (135125188, 135125188, 135125188, 135125188) >>> m = [1,2,3] >>> m1 = m >>> m2 = list(m) >>> m3 = m[:] >>> id(m), id(m1), id(m2), id(m3) (135144364, 135144364, 135144972, 135144076) >>>
![[User Picture]](http://lj.rossia.org/userpic/952/915) | From: | uri |
Date: | December 15th, 2008 - 01:18 am |
---|
| | | (Link) |
|
Практически некропост, да, однако обнаружил, что забыл сказать "Спасибо". Спасибо. | |