Python內建hash函式為什麼執行兩次值不一樣

2021-09-29 08:23:07 字數 958 閱讀 5066

解釋一

python的字串hash演算法並不是直接遍歷字串每個字元去計算hash,而是會有乙個secret prefix和乙個secret suffix,可以認為相當於是給字串加鹽後做hash,可以規避一些規律輸入的情況

顯然這個secret前字尾的值會直接影響計算結果,而且它有乙個啟動時隨機生成的機制,只不過,在2.x版本中,這個機制預設是關閉的,前字尾每次啟動都設定為0,除非你改了相關環境變數來要求隨機,而在3.x中修改了預設行為,如果你不配置環境變數,則預設是隨機乙個前字尾值,這樣每次啟動都會不同

這個環境變數是pythonhashseed,無論在2.x還是3.x中,配置為乙個正整數,將作為隨機種子;配置為0,則secret前字尾預設清零(和2.x預設行為就一樣了),配置為空串或「random」,則表示讓程序隨機生成(和3.x預設行為一樣)

具體為啥要這麼做,猜測乙個是為了安全性(防字串hash表的攻擊,比如php曾經碰到的攻擊),另乙個可能也是強調不要依賴一些內建結果,因為這種演算法可能隨著版本而更新,避免有些使用者不看文件,誤以為是永遠不變的

解釋二set/dict的hash還真就是這個玩意實現的,因為它保證了在同乙個直譯器程序裡相同字串hash一致。

因為cpython 3.x裡的str,它的實體是unicode物件,實體是個utf-8 bytes或者是wstr(嗯這裡真特麼有個『或者』),並且通過乙個叫做unicodedata_db的玩意來實現快取(不然就沒法兒保證str物件的不可變與位址一致性了)。

於是乎當你調內部hash的時候,反正不同程序中的直譯器不會共用乙個unicodedata_db,這個直譯器程序裡的字串的hash到另乙個程序裡指不定連個字串都不是,所以在計算這個內部hash的時候加入了乙個code_magic的玩意,同時也均攤了一把複雜度,省得這個db以及set/dict對特定資料表現出極差效能。再說了,誰也不會傻到拿個直譯器內部hash去做跨程序交換。

所以真需要做可重現可跨程序保持一致性的hash,請用hashlib。

內建函式高階 hash

class foo pass obj1 foo obj2 foo print hash obj1 記憶體位址 136382060082 print hash obj1 記憶體位址 136382060082 print hash obj1 記憶體位址 136382060082 print hash o...

python重寫內建函式 python 內建函式

說明 zip 函式用於將可迭代的物件作為引數,將物件中對應的元素打包成乙個個元組,然後返回由這些元組組成的列表。如果各個迭代器的元素個數不一致,則返回列表長度與最短的物件相同,利用 號操作符,可以將元組解壓為列表。語法 zip iterable1,iterable2,引數 iterable 乙個或多...

python內建函式簡稱 Python內建函式詳解

此文參考python文件,然後結合自己的理解,寫下來,一方面方便自己,讓自己好好學習,順便回憶回憶 另一方面,讓喜歡的盆友也參考一下。經查詢,3.6版本總共有68個內建函式,主要分類如下 數 算 7個 型別轉換 24個 序列操作 8個 物件操作 9個 反射操作 8個 變數操作 2個 互動操作 2個 ...