Я возился с генераторами Python и итерируемым классом, просто для развлечения. По сути, я хотел проверить то, в чем я никогда не был слишком уверен: классы в Python имеют значительные накладные расходы, и лучше полагаться на методы, реализующие yield
, а не на классы, реализующие протокол итератора, если ты сможешь.
Я не смог найти удовлетворительного объяснения этой темы в Google, поэтому решил проверить их самостоятельно, используя эти два простых скрипта: func_iter.py
и class_iter.py
Вот func_iter.py
:
#!/usr/bin/env python
import time
x = 0
def create_generator(num):
mylist = range(num)
for i in mylist:
yield i
t = time.time()
gen = create_generator(100000)
for i in gen:
x = x + i
print "%.3f" % (time.time() - t)
А вот class_iter.py
:
#!/usr/bin/env python
import time
x = 0
class Generator(object):
def __init__(self, num):
self.start = 0
self.end = num
def __iter__(self):
return self
def next(self):
if self.start == self.end:
raise StopIteration
else:
self.start = self.start + 1
return self.start
t = time.time()
gen = Generator(100000)
for i in gen:
x = x + i
print "%.3f" % (time.time() - t)
Затем я запускал каждый из них 10 раз, используя это в bash (для class_iter. py
, например):
for i in {1..10}; do ./class_iter.py; done
А вот среднее время работы для каждого из них:
class_iter.py: 0.0864
func_iter.py: 0.0307
Теперь мои вопросы:
class_iter.py
выполнялся почти в три раза дольше, чем func_iter.py
?РЕДАКТИРОВАТЬ: Как предложил Дакав, я также попытался запустить func_iter.py
, используя xrange
вместо range
. Это уменьшает его среднее время работы до 0,0263 секунды.