摘要:大多數(shù)情況下,相比計算這些不同對象類型的值,直接計算對象所在內(nèi)存地址整數(shù)的值性能更高,這也就是為什么不是計算的值,而是計算所在內(nèi)存地址的值閱讀更多手動漢化的過程模擬登陸字符圖像識別數(shù)字字母混合爬取貓眼實時票房數(shù)據(jù)
dict 的高性能與其存儲方式是分不開的,我們知道 dict 的存儲是基于哈希表(又稱散列表),需要計算 hash 值,那么是計算誰的 hash 值呢?是像別人說的:存儲 dict 元素前計算 key 的 hash 值?
驗證這里先創(chuàng)建個字典
>>> my_dict = {"a": "apple", "b": "banana"}
由于哈希表是一塊連續(xù)的內(nèi)存空間(數(shù)組),在不考慮 hash 值沖突的情況下,如果計算的是 key 的 hash 值,那么:"a" 的 hash 值與 "b" 的 hash 值之間的差值 與 "a" 的內(nèi)存地址與 "b" 的內(nèi)存地址之間的差值(可理解為內(nèi)存地址里的距離) 相等才對,也就是說以下的等式成立才對
hash("a") - hash("b") == id("a") - id("b")
但事實上面等式返回的是 False
>>> hash("a") - hash("b") == id("a") - id("b") False
先看看其中各項的具體值是多少
>>> hash("a") -7336862871683211644 >>> hash("b") 3607308758832868774 >>> id("a") 1290454097736 >>> id("b") 1290454096056
>>> id("a") - id("b") 1680 >>> hash("a") - hash("b") -10944171630516080418
可以很明顯得看到差距還是挺大的
這說明計算的不是 key 的 hash 值(這種說法不夠嚴(yán)謹(jǐn)),那計算的是什么呢?
在不考慮 hash 沖突的情況下, "a" 所在內(nèi)存地址的 hash 值與 "b" 所在內(nèi)存地址的 hash 值之間的差值 和 "a" 的內(nèi)存地址與 "b" 的內(nèi)存地址之間的差值 相等,也就是說以下的等式成立才對
hash(id("a")) - hash(id("b")) == id("a") - id("b")
>>> hash(id("a")) - hash(id("b")) == id("a") - id("b") True >>> id("a") - id("b") 1680 >>> hash(id("a")) - hash(id("b")) 1680
下面再多驗證幾個
>>> my_dict["c"] = "cherry" >>> hash(id("b")) - hash(id("c")) == id("b") - id("c") True >>> id("b") - id("c") 791760 >>> hash(id("b")) - hash(id("c")) 791760
>>> a["d"] = "date" >>> hash(id("d")) - hash(id("c")) == id("d") - id("c") True >>> id("d") - id("c") 1400 >>> hash(id("d")) - hash(id("c")) 1400
到這里就可以證明上面的結(jié)論
為何計算的是 key 所在的內(nèi)存地址的 hash 值?比如上面的"a"(1 個字符) 明顯比其所在的內(nèi)存地址 1290454097736(13 個字符)要短。短的計算不是更快嗎?
記住一句話:Python 中一切皆對象,"a"是個 str 對象,1290454097736 是個 int 對象
>>> type("a")>>> type(id("a"))
一個對象里不是僅僅存儲對應(yīng)值,它還有很多屬性(含方法),來看看誰的屬性多
>>> len(dir("a")) 77 >>> len(dir(id("a"))) 70
str 對象比 int 對象多 7 個屬性
它們都有個叫 __sizeof__() 的魔法方法,用于獲取當(dāng)前對象所占用的內(nèi)存空間大?。ㄗ止?jié))
>>> id("a").__sizeof__() 32 >>> "a".__sizeof__() 50
從上面可以發(fā)現(xiàn):雖然 "a" 看起來只有 1 個字符,但其占用的內(nèi)存空間要大于其內(nèi)存地址 id("a") 所占用的空間
當(dāng)然這不是主要原因,Python 解釋器會將其轉(zhuǎn)換為適當(dāng)?shù)臄?shù)據(jù)類型再進行 hash 計算
不過,dict 的 key 不僅僅可以是 str 對象,也可以是 int、bytes、fromzenset 等這些可哈希(hashable)對象,可哈希對象都是不可變(immutable)對象(注意:反之不一定成立,如 tuple),不可變對象內(nèi)存地址不變。大多數(shù)情況下,相比計算這些不同對象類型的 hash 值,直接計算對象所在內(nèi)存地址(整數(shù))的 hash 值性能更高,這也就是為什么不是計算 key 的 hash 值,而是計算 key 所在內(nèi)存地址的 hash 值
閱讀更多手動漢化 PyCharm 的過程
模擬登陸Github
字符圖像識別——數(shù)字字母混合
爬取貓眼實時票房數(shù)據(jù)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42440.html
摘要:前幾天發(fā)了一篇名為存儲的元素前是計算的值的文章,因缺乏相關(guān)的背景知識,導(dǎo)致得出了不正確的推論。反正存儲的元素前還是計算的值,但這只是散列函數(shù)中的其中一個過程或步驟。 前幾天發(fā)了一篇名為 存儲 dict 的元素前是計算 key 的 hash 值? 的文章,因缺乏相關(guān)的背景知識,導(dǎo)致得出了不正確的推論。那篇文章的推論是 在不考慮 hash 沖突的情況下, a 所在內(nèi)存地址的 hash 值與...
摘要:若對于關(guān)鍵字集合中的任一個關(guān)鍵字,經(jīng)散列函數(shù)映象到地址集合中任何一個地址的概率是相等的,則稱此類散列函數(shù)為均勻散列函數(shù),這就是使關(guān)鍵字經(jīng)過散列函數(shù)得到一個隨機的地址,從而減少沖突。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之?dāng)?shù)據(jù)結(jié)構(gòu)篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點: 1、掌握常見的字典創(chuàng)建,查詢,判別方法;2、了解字典中的defa...
摘要:它們都使用來做事件循環(huán),不過是單線程的服務(wù)器也是多線程的,只不過除了主線程以外,其他線程沒有,只是會進行一些后臺存儲工作,而是多線程的。支持設(shè)置過期時間,即,但是內(nèi)部并不定期檢查數(shù)據(jù)是否過期,而是客戶進程使用該數(shù)據(jù)的時候,會 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實踐干貨哦~ 本文由Super發(fā)表于云+社區(qū)專欄 memcached和redis,作為近些年最常用的緩存服務(wù)器,相...
摘要:默認(rèn)是英文界面,如果想漢化它,網(wǎng)上有很多相關(guān)的漢化丁可以下載。 showImg(https://segmentfault.com/img/remote/1460000016400154); PyCharm 默認(rèn)是英文界面,如果想漢化它,網(wǎng)上有很多相關(guān)的漢化?丁可以下載。 我的 Pycharm 版本是 pycharm-professional-2018.2.2,這里僅簡單展示手動漢化的原...
閱讀 925·2021-10-18 13:32
閱讀 3527·2021-09-30 09:47
閱讀 2168·2021-09-23 11:21
閱讀 1893·2021-09-09 09:34
閱讀 3493·2019-08-30 15:43
閱讀 1533·2019-08-30 11:07
閱讀 1072·2019-08-29 16:14
閱讀 737·2019-08-29 11:06