2014-04-08 10 views
5

Mam następujący kod w Pythonie:Python Generator, który daje więcej wyników zajmuje więcej czasu, aby stworzyć

import time 
import sys 

def returnlist(times): 
    t = time.time() 
    l = [i for i in range(times)] 
    print "list: {}".format(time.time() - t) 
return l 

def returngenerator(times): 
    t = time.time() 
    g = (i for i in range(times)) 
    print "generator: {}".format(time.time() - t) 
    return g 

g = returngenerator(times) 
l = returnlist(times) 

1.W razy = 1000000 uzyskać wyniki:

generator: 0.107323884964

lista: 0,225493192673

2.Dla razy = 10000000 otrzymuję :

generator: 0,856524944305

lista: 1,83883309364

rozumiem dlaczego 2nd lista zajęłoby więcej czasu, aby stworzyć ale dlaczego 2nd generator zająć więcej czasu, jak również? Zakładałem, że ze względu na leniwą ocenę stworzenie tego pierwszego czasu zajęłoby mniej więcej tyle samo czasu.

Używam tego programu na zasadzie Ubuntu VM

+4

Czy używasz Pythona 2? Jeśli tak, użyj 'xrange' zamiast' range'. – Carsten

+0

@Carsten ma całkowicie rację, powody, dla których jest to wolniejsze w pythonie-2, polega na tym, że 'zasięg' stał się leniwy (to znaczy zwraca generator) z pythonem-3, zanim ocenił pełną listę. –

+0

Więc biorę to, że nigdy nie powinienem używać range() w generatorach bulding. Czy użycie range() oznacza, że ​​za każdym razem, gdy ma zostać zwrócona nowa wartość generatora, należy ponownie utworzyć całą listę range()? – GeorgeG

Odpowiedz

5

Problem w kodzie to funkcja range. W Pythonie 2 tworzy listę. W przypadku dużych list, takich jak te w testach porównawczych, staje się to problemem. W języku Python 3, range zwraca generator. Obejściem dla Pythona 2 jest użycie funkcji l23.

Jako test, stwórzmy benchmarku funkcji takich jak twoje, ale przy użyciu XRange:

def returngenerator2(times): 
    t = time.time() 
    g = (i for i in xrange(times)) 
    print "generator2: {}".format(time.time() - t) 
    return g 

i przetestować go:

>>> l = returnlist(10**7) 
list: 0.580000162125 
>>> g = returngenerator(10**7) 
generator: 0.115000009537 
>>> x = returngenerator2(10**7) 
generator2: 0.0 
>>> x2 = returngenerator2(10**8) 
generator2: 0.0 
>>> x3 = returngenerator2(10**9) 
generator2: 0.0 

wydaje się działać. :)

0

Ponieważ range() zwraca rzeczywistą listę w Pythonie 2. W Pythonie 3, to został zmieniony tak, że range() był generator. Użyj xrange() w Pythonie 2, aby poprawić wydajność.

Powiązane problemy