2013-02-27 14 views
8

Po prostu zauważyłem, że podczas korzystania z Python3 przetasowanie listy z random.shuffle wymaga około połowy środowiska wykonawczego podczas jawnego przesyłania funkcji random.random dla random argument słowa kluczowego. Sprawdziłem, czy Python2 ma ten sam problem, ale stwierdził, że występuje tylko w Python3.Krótszy czas wykonywania funkcji `random.shuffle` podczas używania` random.random` jako argumentu ze słowem kluczowym w Python3

używam następujący kod do mierzenia czasu pracy dwóch wersjach:

from timeit import Timer 
t1 = Timer("random.shuffle(l)", "import random; l = list(range(100000))") 
t2 = Timer("random.shuffle(l, random = random.random)", "import random; l = list(range(100000))") 
print("With default rand: %s" % t1.repeat(10,1)) 
print("With custom rand: %s" % t2.repeat(10,1)) 

Zrobiłem testcase at ideone, aby zobaczyć z Python3 i tego samego kodu z Python2.

Według documentation for shuffle ta sama funkcja random.random jest używany w przypadku domyślnym kiedy pominąć opcjonalny argument słowa kluczowego random, więc nie powinno być żadnej różnicy gdy daję mu taką samą funkcję do generowania liczb losowych, jak w przypadku domyślnym .

Sprawdziłem odpowiednich źródeł (python2 vs. Python3) dla funkcji w Lib/random.py foldery shuffle i okazało się, że zachowują się w ten sam sposób jeśli I jawnie wywołać wersję Python3 z funkcją dla słowa kluczowego random. Jeśli pominę ten argument, Python3 użyje funkcji pomocnika _randbelow, więc powinien on być źródłem mojego problemu. Nie rozumiem, dlaczego Python3 używa _randbelow, ponieważ spowalnia on shuffle w dół. O ile rozumiem, jego zaletą jest generowanie arbitralnie dużych liczb losowych, ale nie powinno to spowalniać mojego tasowania listy, która ma mniej niż 2^32 elementów (w moim przypadku 100000).

Czy ktoś może mi wyjaśnić, dlaczego widzę taką różnicę w środowiskach wykonawczych, chociaż powinny one być bliżej siebie, gdy używam Python3?

P.S .: Należy zauważyć, że nie jestem zainteresowany, dlaczego środowisko wykonawcze z Python2 jest lepsze niż w Python3, ale różnica w czasie wykonywania, gdy argument Python3 jest używany w Python3, a nie w Pythonie3.

Odpowiedz

4

Docstring w funkcji random.shuffle jest sprzeczny z kodem. W python 2.7.2+ na docstring jest poprawna:

def shuffle(self, x, random=None, int=int): 
    """x, random=random.random -> shuffle list x in place; return None. 

    Optional arg random is a 0-argument function returning a random 
    float in [0.0, 1.0); by default, the standard random.random. 
    """ 

    if random is None: 
     random = self.random 
    for i in reversed(xrange(1, len(x))): 
     # pick an element in x[:i+1] with which to exchange x[i] 
     j = int(random() * (i+1)) 
     x[i], x[j] = x[j], x[i] 

Ale w Pythonie 3.2 znajdziemy:

def shuffle(self, x, random=None, int=int): 
    """x, random=random.random -> shuffle list x in place; return None. 

    Optional arg random is a 0-argument function returning a random 
    float in [0.0, 1.0); by default, the standard random.random. 
    """ 

    randbelow = self._randbelow 
    for i in reversed(range(1, len(x))): 
     # pick an element in x[:i+1] with which to exchange x[i] 
     j = randbelow(i+1) if random is None else int(random() * (i+1)) 
     x[i], x[j] = x[j], x[i] 

Więc docstring nadal opowiada starą historię, ale teraz domyślna funkcja używana jest przypadkowa .randbelow

Powiązane problemy