2013-02-27 15 views
8

我剛剛觀察到,當使用Python3時,對random.shuffle列表進行的洗牌需要大約一半的運行時,因爲它明確提交函數random.randomrandom關鍵字參數。我檢查了Python2是否有同樣的問題,但發現它只發生在Python3中。當在Python3中使用`random.random`作爲關鍵字參數時`random.shuffle`的運行時間更短

我用下面的代碼來衡量這兩個版本的運行時間:

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)) 

我做了一個testcase at ideone您與Python3與Python2相同的代碼見。

按照documentation for shuffle相同功能random.random在默認情況下使用時,我省略可選關鍵字參數random,所以應該沒有區別,當我給它同樣的功能來生成隨機數作爲在默認情況下, 。

我檢查了各自的來源(Python2與Python3)在Lib/random.py文件夾中的shuffle功能,發現他們的行爲方式相同如果我明確地爲random關鍵字的函數調用Python3版本。如果我省略這個參數,Python3使用幫助函數_randbelow,所以應該有我的問題的根。我不明白爲什麼Python3使用_randbelow,因爲它減慢了shuffle。據我瞭解,它的好處在於產生任意大的隨機數,但它不應該減慢我的序列少於2^32個元素(在我的情況下爲100000)的洗牌速度。

爲什麼我看到在運行時這樣的差異,儘管他們應該更接近在一起的時候我用Python3誰能給我解釋一下?

P.S .:請注意我對Python2運行時比Python3更好的原因並不感興趣,但運行時在Python3中使用參數rand=rand.rand參數與僅在Python3中使用參數時不同。

回答

4

函數random.shuffle中的文檔字符串與代碼相矛盾。 在蟒蛇2.7.2+的文檔字符串是正確的:

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] 

但是在Python 3.2,我們發現:

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] 

所以文檔字符串還告訴老故事,但現在使用的默認功能是隨機的.randbelow

相關問題