Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 7, 2013 14:09:58

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

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

В некоторых случаях генераторы списков существенно обгоняют даже map+filter, не то что for, ввиду отсутствия необходимости вызывать функцию

def foo(x):
    return x % 2
def bar(x):
    return x > 10
def func1():
     lst = [foo(x) for x in xrange(10000000) if bar(x)]
def func2():
     lst = filter(bar, map(foo, xrange(10000000)))
t1 = timeit.Timer(func1, 'from __main__ import func1, foo')
t2 = timeit.Timer(func2, 'from __main__ import func2, foo')
print t1.timeit(1)
print t2.timeit(1)
2.43812799454
2.16352391243

# -*- coding:utf-8 -*-
import timeit
....
def func1():
     lst = [x % 2 for x in xrange(10000000) if x > 10]
def func2():
     lst = filter(bar, map(foo, xrange(10000000)))
....
0.842472791672
2.13915705681
def func1():
     lst = [x % 2 for x in xrange(10000000) if x > 10]
def func2():
     lst = filter(lambda x: x > 10, map(lambda x: x % 2, xrange(10000000)))
0.844331979752
2.1546831131



Офлайн

#2 Дек. 8, 2013 15:04:19

VadimR
Зарегистрирован: 2013-06-06
Сообщения: 14
Репутация: +  1  -
Профиль   Отправить e-mail  

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

user_uid = '10002'
user_name = next(x.split(':')[0] for x in open('passwd.txt') if x.split(':')[2] == user_uid)
print(user_name)

Офлайн

#3 Дек. 9, 2013 00:08:18

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

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

PooH
Имеется ввиду, что после того, как он найдет нужный элемент, итерация все равно будет выполнена до конца.
c чего это ?
итераторы для того и делались, чтобы их до конца не выполнять

например, itertools.count() - бесконечный итератор

>>> import itertools
>>> it = itertools.count()
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>>

так же и с файлами, они - итераторы по строкам
filter() приведена для третьего питона, в нём это itertools.ifilter(), перенесённая в ядро


FishHook
В некоторых случаях генераторы списков существенно обгоняют даже map+filter, не то что for, ввиду отсутствия необходимости вызывать функцию
это не из-за этого, во втором питоне эти функции создают списки, которые потом используются для перебора (создания итераторов)
поэтому как filter(), так и map() нужно заменить на аналоги из itertools
и уже тогда сравнивать



Отредактировано py.user.next (Дек. 9, 2013 00:14:30)

Офлайн

#4 Дек. 9, 2013 01:08:59

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

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

py.user.next
поэтому как filter(), так и map() нужно заменить на аналоги из itertools
и уже тогда сравнивать

import timeit
from itertools import ifilter, imap
def foo(x):
    return x % 2
def bar(x):
    return x > 0
    
def func1():
     sum( [foo(x) for x in xrange(100000) if bar(x)] )
     
def func2():
     sum( ifilter(bar, imap(foo, xrange(100000))) )
     
t1 = timeit.Timer(func1, 'from __main__ import func1, foo')
t2 = timeit.Timer(func2, 'from __main__ import func2, foo')
print t1.repeat(3, 10)
print t2.repeat(3, 10)

[0.6189520359039307, 0.6175930500030518, 0.620582103729248]
[0.568681001663208, 0.5698568820953369, 0.5771739482879639]


def func1():
     sum( [x % 2 for x in xrange(100000) if x > 0] )
    
def func2():
     sum( ifilter(lambda x: x > 0, imap(lambda x: x % 2, xrange(100000))) )
     

[0.20290303230285645, 0.2011399269104004, 0.19998598098754883]
[0.5880811214447021, 0.5824930667877197, 0.5833539962768555]



Отредактировано Budulianin (Дек. 10, 2013 22:58:04)

Офлайн

#5 Дек. 9, 2013 01:13:34

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

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

py.user.next
это не из-за этого, во втором питоне эти функции создают списки, которые потом используются для перебора (создания итераторов)
поэтому как filter(), так и map() нужно заменить на аналоги из itertools
и уже тогда сравнивать

Как видно, вызов функций, тоже замедляет работу



Офлайн

#6 Дек. 9, 2013 01:24:49

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

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

Budulianin
[0.6189520359039307, 0.6175930500030518, 0.620582103729248]
[0.568681001663208, 0.5698568820953369, 0.5771739482879639]
ну вот, что и требовалось доказать

Budulianin
Как видно, вызов функций, тоже замедляет работу
во втором случае коды не эквивалентные
хочешь сравнить - возьми включение с функцией и включение без функции - их и сравнивай



Офлайн

#7 Дек. 9, 2013 01:40:45

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

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

py.user.next
во втором случае коды не эквивалентные
хочешь сравнить - возьми включение с функцией и включение без функции - их и сравнивай

Без imap в filter? Генератор списка всё равно быстрее будет



Офлайн

#8 Дек. 9, 2013 04:19:48

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

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

py.user.next
нужно заменить на аналоги из itertools
и уже тогда сравнивать
Не согласен, в этом случае сравнивать надо не
[x for x ]
, а
(x for x)



Офлайн

#9 Дек. 10, 2013 22:42:12

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

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

FishHook
Не согласен, в этом случае сравнивать надо не
это да, не думаю, что будут сильно различаться
можно для второй функции list сделать

Budulianin, убери скобки возле return, не позорься
сначала убери скобки, запомни это
а потом и весь return убери и lst = тоже - не нужно это всё для замеров



Отредактировано py.user.next (Дек. 10, 2013 22:43:30)

Офлайн

#10 Дек. 10, 2013 22:59:52

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

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

py.user.next

На счёт того, что return и lst = не нужны для замеров, это понятно

А что позорного в return() ? Если интерпретатор это понимает



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version