Генераторы vs классы

    Очень маленький пост о том, что выбрать: генератор или класс, когда реализация возможна обоими способами.

    Не сложный выбор


    Простая задача: рассчитывать скользящее среднее. Первоначальная реализация была в виде класса, но не давало покоя наличие генераторов, которые как-то очень подходили под концепцию. Но простой тест помог сделать выбор.

    class EMA(object):
    
        def __init__(self, alpha=0.5):
            self.value = 0
            self.alpha = alpha
    
        def update(self, price):
            self.value = self.value + self.alpha * (price - self.value)
    
    def ema(alpha=0.5):
        result = 0
        previous = (yield)
        while True:
            price = (yield result)
            result = result + alpha(price - result)
    

    Теперь проводим 2 замера: создаём миллион генераторов и миллион классов, исследуем время и память:
    Реализация Память Время
    Генераторы 433,012 Мб 0:00:02.330000
    Классы 200,504 Мб 0:00:01.807000

    Вывод: классы в Python сделаны очень легковесными. Используйте их смело.

    P.S. Под дебаггером классы создавались более 6 секунд, а время создания генераторов увеличилось всего на 1 секунду. Не проводите замер под отладчиком.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 13

      +2
      Вы просто не умеете их готовить. Попробуйте, например, сравнить range и xrange от нескольких миллионов. В некоторых случаях использование yield намного удобнее «классического» подхода.
        0
        Безусловно я не против генераторов! Сам использую их постоянно. Задача статьи — показать, что выбирать генераторы, предполагая, что они очень быстрые, неправильно.
          0
          Что за странная постановка вопроса? Кажется, Вы излишне утрируете: ни от кого таких смешных формулировок я не слышал. Всё зависит от конкретной задачи, и думаю, что каждый мало-мальски опытный разработчик это понимает и учитывает.
          0
          И где в xrange yield?
        • UFO just landed and posted this here
            +1
            На самом деле мне нужен как раз миллион, а точнее 7. Так как это кусок кода оптимизатора торговых стратегий. Испытать на большом потоке данных ещё предстоит )
            • UFO just landed and posted this here
                0
                Получается да, так как поступает много данных, формирование и чтение которых занимает много времени. Проще один раз прочитать, миллион вариаций рассчитать.
            +1
            Во-первых, если есть сравнение производительности, то нужно указывать, как вы его производили.
            Во-вторых, вы сравниваете только время создания без сарвнения скорости работы, это действительно такой специфичный случай?
            В-третих, у меня получилось timeit-ом и huppy одинаковое время создания объектов и разница в памяти 356 и 572 Мб.
              –2
              У меня этот блок работать будет не под timeitом. Поэтому просто запустил, просто посмотрел, просто сравнил и выбрал.
                0
                +1, время создания одинаковое. Генератор считает вдвое быстрее.
                0
                Завидую я вам с несложностью выбора.

                Быстродействие кода — это один аспект из многих. Один из основных — сокращение количества ошибок. Вероятность, что программист допустит ошибку в генераторе выше, чем в случае с классом, больше моментов нужно учитывать. При прочих равных я всегда буду использовать максимально тупой и незатейливый код, использующий 20% от возможностей языка. Вот это уже поднапряжет мозг джуниора: previous = (yield)

                Второй момент — это полная некорректность сравнения класса и функции. Результатом выполнения может быть одно и то же, но они работают абсолютно по разному, по разному относятся к персистентности и подразумевают разный характер вызовов, генератор не предназначен для того, чтобы дернуть его пару раз, потом пойти погулять и потом скормить ему что ни будь. Это — функция от определенных данных, которая производит вычисление. Класс группирует функции и данные в некую целостную единицу.

                А бенчмаркать (криво) вычислительные операции на питоне. Да это же гребаный лол. Лучше раскрыть для себя вот этот раздел документации: docs.python.org/extending/extending.html
                  0
                  +1, согласен! генератор должен кормиться непрерывними последовательностями и сразу

                Only users with full accounts can post comments. Log in, please.