Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 4, 2013 16:52:57

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

smoke853
В смысле какая скорость? в первом случае время выполнения = 0.755, во втором = 0.002, очевидно что второй вариант работает быстрее.

Ну и что ты посчитал ? Твоя функция вернула генератор, а не результат работы генератора. Естественно создать генератор быстрее. А вот когда потребуется, чтобы твой генератор выдал значение, потратится ещё время, на его вычисление.



Офлайн

#2 Дек. 4, 2013 17:18:03

smoke853
Зарегистрирован: 2012-10-02
Сообщения: 123
Репутация: +  15  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Budulianin
Естественно создать генератор быстрее. А вот когда потребуется, чтобы твой генератор выдал значение, потратится ещё время, на его вычисление.

Да, понятно что потратится еще время на его вычисление, допустим: n-e время потратится на создание генератора + n-е время потратится на вычисление, но я думаю что время выполнения будет все равно быстрее чем если бы использовался return или я ошибаюсь?

Офлайн

#3 Дек. 4, 2013 17:23:15

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

smoke853
Да, понятно что потратится еще время на его вычисление, допустим: n-e время потратится на создание генератора + n-е время потратится на вычисление, но я думаю что время выполнения будет все равно быстрее чем если бы использовался return или я ошибаюсь?

Если одна функция просто вычисляет и возвращает значение, а вторая создаёт генератор, вычисляет и возвращает значение. Где меньше действий ?

Или ты думаешь, что напишешь волшебное слово yield и всё взлетит ? :)

Генераторы были созданы не для скорости, а для того, чтобы память не расходовать там, где этого не нужно.


В задачи ТС, вообще нигде генератор ниразу не нужен. Ему просто нужно первое подходящее значение вернуть и всё. А ему зачем-то генераторы подавай.



Отредактировано Budulianin (Дек. 4, 2013 17:27:42)

Офлайн

#4 Дек. 4, 2013 17:29:38

smoke853
Зарегистрирован: 2012-10-02
Сообщения: 123
Репутация: +  15  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Budulianin
Или ты думаешь, что напишешь волшебное слово yield и всё взлетит ?
Ну примерно так и думал , конечно все не взлетит, но думал что в разы будет работать быстрее.

Офлайн

#5 Дек. 4, 2013 17:37:28

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

smoke853
Ну примерно так и думал , конечно все не взлетит, но думал что в разы будет работать быстрее.

Просто надо видеть противоречия, и не кушать их.
На твоём скрине, время выполнения “одних и тех” же операций очень отличаются.

Вторая функция, вроде бы делает “такие же” действия, НО работает в 375 раз быстрее, это уже должно насторожить.



Отредактировано Budulianin (Дек. 4, 2013 17:38:41)

Офлайн

#6 Дек. 4, 2013 22:58:32

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9874
Репутация: +  854  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

>>> with open('/etc/passwd', encoding='utf-8') as fin:
...     line = next(filter(lambda s: s.split(':')[0] == 'ftp', fin))
... 
>>> line
'ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin\n'
>>>
для второго - itertools.ifilter()



Офлайн

#7 Дек. 4, 2013 23:20:46

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

py.user.next

filter перебирает все элементы



Офлайн

#8 Дек. 5, 2013 20:49:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9874
Репутация: +  854  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Budulianin
filter перебирает все элементы
нет, это итератор

>>> it = filter(None, [1, 2, 3])
>>> it
<filter object at 0x7fd71400ca50>
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>



Офлайн

#9 Дек. 6, 2013 04:36:36

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

py.user.next
нет, это итератор
Имеется ввиду, что после того, как он найдет нужный элемент, итерация все равно будет выполнена до конца.



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#10 Дек. 6, 2013 22:46:55

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Budulianin
Вообще-то генератор списков это просто “синтаксический сахар” и по реализации ничем не отличается, от обычного for. Следовательно он работает с такой же скоростью.

Поправочка, чтобы никого в заблуждение не вводить.

Из Лутца:
“генераторы списков могут выполняться значительно быстрее (зачастую почти в два раза), чем
инструкции циклов for, потому что итерации выполняются со скоростью
языка С, а не со скоростью программного кода на языке Python. Такое преимущество в скорости особенно важно для больших объемов данных.”

Проверяем:

def func1():
     lst = [x for x in range(10000)]
def func2():
     lst = []
     for x in range(10000):
          lst.append(x)
t1 = timeit.Timer(func1, 'from __main__ import func1')
t2 = timeit.Timer(func2, 'from __main__ import func2')
t1.repeat(3, 1000)
[1.3615523760017822, 1.1045241789979627, 1.1151962050025759]
t2.repeat(3, 1000)
[2.1324967270011257, 2.1218632529999013, 2.120350769997458]



Отредактировано Budulianin (Дек. 6, 2013 22:47:59)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version