Записки реликта - Странности со списками в Python [entries|archive|friends|userinfo]
Latimeria chalumnae

[ userinfo | ljr userinfo ]
[ archive | journal archive ]

Странности со списками в Python [Nov. 30th, 2008|12:25 pm]
Previous Entry Add to Memories Tell A Friend Next Entry
[Tags|, , ]

Тем временем то ли нашёл ещё одну крупную кривизну то ли в Питоне, то ли в собственных руках.

Был мне нужен список списков одинаковых значений. И я его, недолго думая, организовал строчкой:
L = [[1] * 30] * 30]

Но после этого, попытавшись с этим списком работать, я обнаружил, что присваивание 0 какому-то из элементов в строке обнуляет всю строку. Немножко потупив, я догадался, что, скорее всего, дело в питоновском implicit sharing (кстати, что-то я с утра туплю — есть устоявшийся русский термин?), и написал вместо вышеупомянутой строки цикл:
L = []
for i in range(30):
    М = []
    for j in range(30):
        М += [1]
    L += [М]

Всё немедленно заработало, конечно. "Но осадочек остался". Как-то, по-моему, это "неаккуратненько"©. А вы как думаете?
LinkОставить комментарий

Comments:
[User Picture]
From:[info]pilpilon
Date:November 30th, 2008 - 06:52 pm
(Link)
не должно обнулять строку, должно обнулять столбец.
Это и задумано так, умножать mutables в питоне надо осторожно.
c = [[1]*30 for i in range(30)]
должно быть достаточно.
[User Picture]
From:[info]yushi
Date:November 30th, 2008 - 08:16 pm
(Link)
не должно обнулять строку, должно обнулять столбец.
Это и задумано так


А почему? То есть, зачем нужно implicit sharing вообще, я понимаю. Но как и по каким причинам Питон решает, когда из одной переменной пора делать две разных?

Если лень объяснять, просто дайте ссылку, где про это пишут.
[User Picture]
From:[info]pilpilon
Date:December 1st, 2008 - 04:35 pm
(Link)
Сколь я помню, 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]
From:[info]uri
Date:December 15th, 2008 - 01:18 am
(Link)
Практически некропост, да, однако обнаружил, что забыл сказать "Спасибо". Спасибо.