?

Log in

No account? Create an account
   Journal    Friends    Archive    Profile    Memories
 

Attention test - morfizm


Mar. 30th, 2011 02:52 pm Attention test

Find a bug:

class A(list):

    @staticmethod
    def _flatten_item(item):
        return item.split('|')

    def flatten(self):
        # save original list
        copy = list(self)

        # clear list
        for a in self:
            self.remove(a)
 
        # populate it with new lists 
        # as we transform saved elements
        for a in copy:
            self.extend(self._flatten_item(a))
(Syntax highligher used: http://tohtml.com/python/)

11 comments - Leave a commentPrevious Entry Share Next Entry

Comments:

From:raindog_2
Date:March 30th, 2011 11:16 pm (UTC)
(Link)
В-общем, проблема с
for a in self:
  self.remove(a)


Плохо ходить по спику и одновременно из него удалять. Вместо оргинала нужно ходить по копии. Кстати, насколько я помню, идиоматический вариант сделать копию списка - это оператор [:].
From:morfizm
Date:March 30th, 2011 11:32 pm (UTC)
(Link)
Простое упражнение, да :)

Я увидел этот баг своими глазами. Т.е. я понимал, что так не надо делать, сам же написал такой код (проглядел), и сам же словил это в юнит тестах.

* * *

x = x[:] лучше чем x = list(x)?
Последний вариант мне нравится тем, что ты так же можешь копировать и dict, и set. А первым способом только list.

From:raindog_2
Date:March 31st, 2011 12:18 am (UTC)
(Link)
Насчет удаления всех элементов - это какой-то некрасивый метод. Наверняка есть что-то лучше. Может, так -
self[:] = A()

***

Чем лучше [:] - ну, мне кажется, это идиоматический вариант.
То есть концепция "сделать-копию-списка-x" в голове у питониста автомтически превращается в x[:].
Опять же, если бы у тебя уже не было копии, можно было бы написать
for a in self[:]:
По-моему, это красивее, чем создавать новый объект
for a in list(self):

Кроме того, нужно заметить, что х[:] делает shallow copy, и это люди обычно знают. А вот что какую копию делает list(x) - по-моему, с ходу понять трудно. Насколько я понимаю, он тоже делает shallow copy.

Есть ли разница с точки зрения performance - не знаю. Скорее всего, нет.

То, что таким образом можно копировать dict - да, но там были какие-то свои проблемы. Уже не помню - я на питоне несколько лет ничего не писал.
From:raindog_2
Date:March 31st, 2011 12:32 am (UTC)
(Link)
P.S. Насчет удаления элементов - еще можно так, наверное:
del self[:]
From:raindog_2
Date:March 31st, 2011 12:57 am (UTC)
(Link)
Кстати, используя тот же трюк с [:], весь твой класс можно упростить вот так:

class A(list):
  def flatten(self):
    self[:] = sum([x.split('|') for x in self], [])

From:morfizm
Date:March 31st, 2011 03:57 am (UTC)
(Link)
Оба варианта работают ("del self[:]" и "self[:] = A()"). Спасибо, оч. поучительно!
From:raindog_2
Date:March 31st, 2011 04:42 am (UTC)
(Link)
Смотри, какой я еще смешной вариант придумал:
def flatten(self):
  self[:] = '|'.join(self).split('I')
From:raindog_2
Date:March 31st, 2011 04:44 am (UTC)
(Link)
split('|'), а не 'I', конечно. А почему ЖЖ мне не дает комментарии редактировать?
From:morfizm
Date:March 31st, 2011 04:55 am (UTC)
(Link)
В твоём случае, потому что эта фича доступна платным юзерам. А ещё бывает случай, когда кто-то уже ответил на твой комментарий.
From:morfizm
Date:March 31st, 2011 04:53 am (UTC)
(Link)
Красиво!
From:archaicos
Date:March 31st, 2011 04:38 am (UTC)
(Link)
Хе-хе, я тоже как-то имел удовольствие удалять в Си++ что-то откуда-то при помощи итератора и навернулся. Точнее, может даже не навернулся, но точно долго изучал способы правильного удаления.