2014-12-04 48 views
5

說我有一些Python代碼:Python:其中是random.random()播種?

import random 
r=random.random() 

哪裏是r的值在一般接種?
而如果我的操作系統沒有隨機的話,那麼它在哪裏播種?
爲什麼不推薦用於密碼學?有什麼方法可以知道隨機數是什麼?

+0

[這裏](http://stackoverflow.com/questions/10341112/whats-more來到-random-hashlib-or-urandom)你有類似的問題。 – Marcin 2014-12-04 02:01:06

回答

10

關注da代碼

要看看那裏的random模塊「住」在你的系統,你可以在終端中執行:

>>> import random 
>>> random.__file__ 
'/usr/lib/python2.7/random.pyc' 

這使你的路徑.pyc(「編譯」)的文件,通常是與原始.py並排放置,其中可以找到可讀代碼。

讓我們看看這是怎麼回事在/usr/lib/python2.7/random.py

你會看到,它創建了Random類的一個實例,然後(在文件的底部),「促進」該實例的方法,以模塊的功能。整潔的把戲。當random模塊被導入到任何地方時,將創建該類Random的新實例,然後對其值進行初始化並將方法重新分配爲模塊的功能(使其在每次導入的基礎上非常隨機)

_inst = Random() 
seed = _inst.seed 
random = _inst.random 
uniform = _inst.uniform 
triangular = _inst.triangular 
randint = _inst.randint 

,這Random類確實在其__init__方法的唯一事情是播種之:

class Random(_random.Random): 
    ... 
    def __init__(self, x=None): 
     self.seed(x)  
... 
_inst = Random() 
seed = _inst.seed 

所以...如果xNone會發生什麼(無種子已指定)?好吧,讓我們檢查self.seed方法:

def seed(self, a=None): 
    """Initialize internal state from hashable object. 

    None or no argument seeds from current time or from an operating 
    system specific randomness source if available. 

    If a is not None or an int or long, hash(a) is used instead. 
    """ 

    if a is None: 
     try: 
      a = long(_hexlify(_urandom(16)), 16) 
     except NotImplementedError: 
      import time 
      a = long(time.time() * 256) # use fractional seconds 

    super(Random, self).seed(a) 
    self.gauss_next = None 

的意見已經告訴這是怎麼回事?該方法嘗試使用操作系統提供的默認隨機數生成器,如果有沒有,那麼它會使用當前時間作爲種子值。

但是,等等......到底是什麼東西呢?

好了,答案就在這個random.py文件的開頭:

from os import urandom as _urandom 
from binascii import hexlify as _hexlify 

Tadaaa ...種子是從os.urandom

來到一個16字節數比方說,我們正處在一個文明的操作系統,如Linux(具有真實隨機數發生器)。由random模塊使用的種子是一樣的做:

>>> long(binascii.hexlify(os.urandom(16)), 16) 
46313715670266209791161509840588935391L 

爲什麼指定的種子值的原因被認爲沒有那麼大是,random功能是不是真正的「隨機」 ......他們這只是一個非常奇怪的數字序列。但是,鑑於相同的種子,該序列將是相同的。你可以試試這個自己:

>>> import random 
>>> random.seed(1) 
>>> random.randint(0,100) 
13 
>>> random.randint(0,100) 
85 
>>> random.randint(0,100) 
77 

無論何時或如何,甚至在那裏您運行的代碼(只要用於生成隨機數的算法保持不變),如果你的種子是1,你總是會得到整數13,85,77 ......哪種破壞目的(見this關於僞隨機數的產生)另一方面,有use cases這實際上可能是一個理想的功能,但。

這就是爲什麼依靠操作系統隨機數生成器被認爲是「更好」的原因。這些通常基於硬件中斷進行計算,這些中斷非常非常隨機(它包括用於硬盤驅動器讀取的interruptions,由用戶鍵入的擊鍵,移動鼠標......)在Linux中,該O.S.發電機是/dev/random。或者,有點挑剔,/dev/urandom(這是Python的os.urandom實際內部使用的)。區別在於(如前所述)/dev/random使用硬件中斷來生成隨機序列。如果沒有中斷,/dev/random可能會用盡,你可能要等一會兒,直到你可以得到下一個隨機數。 /dev/urandom在內部使用/dev/random,但它保證它將始終爲您準備隨機數。

如果您正在使用Linux,只是做cat /dev/random終端上(並準備打按Ctrl + C,因爲這將真正開始輸出,真正隨機的東西)

[email protected]:/tmp$ cat /dev/random 
_+�_�?zta����K�����q�ߤk��/���qSlV��{�Gzk`���#p$�*C�F"�B9��o~,�QH���ɭ�f�޺�̬po�2o�(=��t�0�p|m�e 
���-�5�߁ٵ�ED�l�Qt�/��,uD�w&m���ѩ/��;��5Ce�+�M���� 
~ �4D��XN��?ס�d��$7Ā�kte▒s��ȿ7_���-  �d|����cY-�j>� 
        �b}#�W<դ���8���{�1» 
.  75���c4$3z���/̾�(�(���`���k�fC_^C 

Python使用OS隨機發電機或時間作爲種子。這意味着,當它用在我能想象用Python的random模塊潛在的弱點的地方是:

  • 在OS沒有實際的隨機數發生器,
  • 在一個裝置,其time.time是始終報告相同時間(有一個破碎的時鐘,基本上)

如果你關心random模塊的實際隨機性,你可以直接去os.urandom或使用隨機數根兒ator pycrypto加密庫。那些大概是更隨機。我說更隨機因爲......

https://stackoverflow.com/a/2146062/289011

形象的靈感來自這個其他SO answer

+0

擁有真正的隨機性並不總是更好。 OP確實詢問了密碼學問題,但即使如此,您應該知道您使用的數據是什麼(例如,Salsa將始終從0開始產生0)。播種一個僞隨機數發生器對於可複製但任意的數據非常有用,特別是對於隨機生成的遊戲中的可重複測試或共享水平。 – 2014-12-04 14:33:42

+0

@YannVernier,正確,正確。這就是爲什麼我添加了一個澄清,說有時使用相同的種子作爲一個功能是可取的。 – BorrajaX 2014-12-04 14:35:43

+2

非常詳細的答案。 – LonelyWebCrawler 2014-12-04 17:20:54