चूँकि सूचियाँ उत्परिवर्तनीय हैं, dict
कुंजी (और set
सदस्यों) को धोने योग्य होने की आवश्यकता है, और हैशिंग उत्परिवर्तित वस्तुएँ एक बुरा विचार है क्योंकि हैश मान होना चाहिए उदाहरण विशेषताओं के आधार पर गणना की चाहिए।
इस जवाब में, मैं कुछ ठोस उदाहरण दूंगा, उम्मीद है कि मौजूदा उत्तरों के शीर्ष पर मूल्य को जोड़ना होगा। प्रत्येक जानकारी set
डेटास्ट्रक्चर के तत्वों पर भी लागू होती है ।
उदाहरण 1 : हैशबल एक उत्परिवर्तित वस्तु है, जहां हैश का मूल्य वस्तु की एक परस्पर विशेषता पर आधारित है।
>>> class stupidlist(list):
... def __hash__(self):
... return len(self)
...
>>> stupid = stupidlist([1, 2, 3])
>>> d = {stupid: 0}
>>> stupid.append(4)
>>> stupid
[1, 2, 3, 4]
>>> d
{[1, 2, 3, 4]: 0}
>>> stupid in d
False
>>> stupid in d.keys()
False
>>> stupid in list(d.keys())
True
उत्परिवर्तन के बाद stupid
, इसे किसी भी लंबे समय तक हुक में नहीं पाया जा सकता है क्योंकि हैश बदल गया है। तानाशाह की चाबी की सूची पर केवल एक रेखीय स्कैन पाता है stupid
।
उदाहरण 2 : ... लेकिन सिर्फ एक स्थिर हैश मान क्यों नहीं?
>>> class stupidlist2(list):
... def __hash__(self):
... return id(self)
...
>>> stupidA = stupidlist2([1, 2, 3])
>>> stupidB = stupidlist2([1, 2, 3])
>>>
>>> stupidA == stupidB
True
>>> stupidA in {stupidB: 0}
False
यह एक अच्छा विचार के रूप में अच्छी तरह से क्योंकि बराबर वस्तुओं हूबहू इस तरह है कि आप उन्हें में एक पा सकते हैं हैश चाहिए नहीं है dict
या set
।
उदाहरण 3 : ... ठीक है, सभी उदाहरणों में निरंतर हैश के बारे में क्या है ?!
>>> class stupidlist3(list):
... def __hash__(self):
... return 1
...
>>> stupidC = stupidlist3([1, 2, 3])
>>> stupidD = stupidlist3([1, 2, 3])
>>> stupidE = stupidlist3([1, 2, 3, 4])
>>>
>>> stupidC in {stupidD: 0}
True
>>> stupidC in {stupidE: 0}
False
>>> d = {stupidC: 0}
>>> stupidC.append(5)
>>> stupidC in d
True
चीजें अपेक्षा के अनुरूप काम करने लगती हैं, लेकिन सोचें कि क्या हो रहा है: जब आपकी कक्षा के सभी उदाहरण समान हैश मान का उत्पादन करते हैं, तो आपके पास हैश की टक्कर तब होगी जब दो से अधिक उदाहरण होंगे जैसे कि dict
या एक में मौजूद कुंजीset
।
my_dict[key]
या key in my_dict
(या item in my_set
) के साथ सही उदाहरण खोजने के लिए कई समानता की जाँच करने की आवश्यकता है क्योंकि वहाँ के उदाहरण हैंstupidlist3
कि तानाशाही कीज़ (सबसे खराब स्थिति में) के उदाहरण हैं। इस बिंदु पर, शब्दकोश का उद्देश्य - ओ (1) देखने - पूरी तरह से हार गया है। यह निम्नलिखित समय (IPython के साथ किया गया) में प्रदर्शित होता है।
उदाहरण 3 के लिए कुछ समय
>>> lists_list = [[i] for i in range(1000)]
>>> stupidlists_set = {stupidlist3([i]) for i in range(1000)}
>>> tuples_set = {(i,) for i in range(1000)}
>>> l = [999]
>>> s = stupidlist3([999])
>>> t = (999,)
>>>
>>> %timeit l in lists_list
25.5 µs ± 442 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit s in stupidlists_set
38.5 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit t in tuples_set
77.6 ns ± 1.5 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
जैसा कि आप देख सकते हैं, हमारे में सदस्यता परीक्षण stupidlists_set
पूरी तरह से एक रैखिक स्कैन की तुलना में भी धीमा है lists_list
, जबकि आपके पास हैश टकराव के भार के बिना एक सेट में अपेक्षित सुपर फास्ट लुकअप समय (कारक 500) है।
टी एल; DR: आप चाबियों के tuple(yourlist)
रूप में उपयोग कर सकते हैं dict
, क्योंकि ट्यूप्स अपरिवर्तनीय और धोने योग्य हैं।