Python字典鍵。“復(fù)雜”的
首先,key in d.keys()保證為您提供與key in ddict相同的值d。
而且,in對(duì)dict或操作(從3.x中dict_keys調(diào)用)返回的對(duì)象的操作 不是 O(N),而是O(1)。keys() __
沒(méi)有真正的“優(yōu)化”。只是使用哈希是在__contains__哈希表上實(shí)現(xiàn)的明顯方法,就像它是實(shí)現(xiàn)的明顯方法一樣__getitem__。
您可能會(huì)問(wèn)這在哪里得到保證。
好吧,不是。映射類型將dict基本上定義為的哈希表實(shí)現(xiàn)collections.abc.Mapping。沒(méi)有什么可以阻止某人創(chuàng)建Mapping的哈希表實(shí)現(xiàn)的,但是仍然可以提供O(N)搜索。但是,要實(shí)現(xiàn)如此糟糕的實(shí)現(xiàn)將是額外的工作,那么為什么要這么做呢?
如果您確實(shí)需要自己證明它,則可以測(cè)試您關(guān)心的每個(gè)實(shí)現(xiàn)(使用探查器,或者通過(guò)將某種類型與自定義一起使用,__hash__并__eq__記錄調(diào)用,或者…),或者閱讀源代碼。
在2.x中,您不想調(diào)用keys,因?yàn)樗鼤?huì)生成一個(gè)list密鑰,而不是一個(gè)KeysView。您可以使用iterkeys,但可能會(huì)生成迭代器或其他不是O(1)的東西。因此,只需將dict本身用作序列即可。
即使在3.x中,也不需要調(diào)用keys,因?yàn)闆](méi)有必要。迭代a dict,檢查其__contains__,并且通常將其視為序列 總是等同于對(duì)其鍵執(zhí)行相同的操作,那么為什么要打擾呢?(當(dāng)然,構(gòu)建瑣碎的宏keyview并進(jìn)行訪問(wèn)將使您的運(yùn)行時(shí)間增加幾納秒,并為程序增加一些擊鍵。)
(尚不清楚d.keys()/d.iterkeys()和d2.x中使用序列運(yùn)算是否等效。除了性能問(wèn)題外,它們?cè)诿總€(gè)cpython,Jython,IronPython和PyPy實(shí)現(xiàn)中均 等效,但是似乎在任何地方都沒(méi)有說(shuō)明。 3.x中的方式。這并不重要;只需使用key in d。)
在進(jìn)行此操作時(shí),請(qǐng)注意以下幾點(diǎn):
if(dict[key] != None):
……將無(wú)法正常工作。如果key不在中dict,則將引發(fā)KeyError而不返回None。
另外,您永遠(yuǎn)不要None使用==或進(jìn)行檢查!=。經(jīng)常使用is。
您可以使用try-或更簡(jiǎn)單地說(shuō),執(zhí)行do if dict.get(key, None) is notNone。但是同樣,沒(méi)有理由這樣做。此外,這將無(wú)法處理None完全有效的物品。在這種情況下,您需要執(zhí)行sentinel = object(); ifdict.get(key, sentinel) is not sentinel:。
因此,正確的寫法是:
if key in d:
更普遍地說(shuō),這是不正確的:
我知道關(guān)鍵字“ in”通常為O(n)(因?yàn)檫@僅表示python遍歷整個(gè)列表并比較每個(gè)元素
in與大多數(shù)其他運(yùn)算符一樣,該運(yùn)算符僅是對(duì)__contains__方法的調(diào)用(或等效于內(nèi)置的C / Java / .NET /RPython)。list通過(guò)迭代列表并比較每個(gè)元素來(lái)實(shí)現(xiàn)它;dict通過(guò)散列值并查找散列來(lái)實(shí)現(xiàn)它;blist.blist通過(guò)走B +Tree來(lái)實(shí)現(xiàn)它;因此,它可以是O(n),O(1),O(log n)或完全不同的東西。
解決方法快速提問(wèn)主要滿足我對(duì)這個(gè)話題的好奇心。
我正在編寫一些帶有SQlite數(shù)據(jù)庫(kù)后端的大型python程序,并且將來(lái)會(huì)處理大量記錄,因此,我需要盡可能地優(yōu)化。
對(duì)于一些功能,我正在字典中搜索關(guān)鍵字。我一直在使用“ in”關(guān)鍵字進(jìn)行原型設(shè)計(jì),并計(jì)劃稍后返回并優(yōu)化這些搜索,因?yàn)槲抑馈癷n”關(guān)鍵字通常為O(n)(因?yàn)檫@僅表示python遍歷整個(gè)列表并進(jìn)行比較每個(gè)元素)。但是,由于pythondict基本上只是一個(gè)哈希映射,因此python解釋器足夠聰明來(lái)解釋:
if(key in dict.keys()): ...code...
至:
if(dict[key] != None): ...code...
它基本上是相同的操作,但頂部為O(n),底部為O(1)。
對(duì)我來(lái)說(shuō),在代碼中使用底部版本很容易,但是后來(lái)我很好奇并以為我會(huì)問(wèn)。
相關(guān)文章:
1. Java8內(nèi)存模型PermGen Metaspace實(shí)例解析2. python excel和yaml文件的讀取封裝3. python如何實(shí)現(xiàn)word批量轉(zhuǎn)HTML4. python3實(shí)現(xiàn)往mysql中插入datetime類型的數(shù)據(jù)5. moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問(wèn)題及解決6. python爬蟲實(shí)戰(zhàn)之制作屬于自己的一個(gè)IP代理模塊7. App啟動(dòng)優(yōu)化-Android性能優(yōu)化8. Docker鏡像管理常用操作代碼示例9. Python中內(nèi)建模塊collections如何使用10. 詳解docker pull 下來(lái)的鏡像都存到了哪里
