पायथन में "हैशेबल" का क्या अर्थ है?


193

मैंने इंटरनेट पर सर्च करने की कोशिश की, लेकिन हैशेबल का अर्थ नहीं खोज पाया।

जब वे कहते हैं कि वस्तुएं हैं hashableया hashable objectsइसका क्या मतलब है?


1
हैशेबल और __hash__()विधि पर प्रलेखन देखें ।
ʇs:oɈ

5
कि खोज योग्य वस्तुओं या कुछ और के लिए खोज करता है, लेकिन कोई भी लिंक यह नहीं बताता है कि वास्तव में क्या
हैश का

जवाबों:


180

से अजगर शब्दकोष :

एक वस्तु hashable है अगर यह एक हैश मान जो अपने जीवनकाल (यह एक जरूरत है के दौरान बदल जाता है कभी नहीं है __hash__()विधि), और अन्य वस्तुओं (यह एक जरूरत की तुलना में किया जा सकता है __eq__()या __cmp__()विधि)। हेशिबल ऑब्जेक्ट जो समान की तुलना करते हैं उनके पास समान हैश मान होना चाहिए।

Hashability किसी वस्तु को शब्दकोश कुंजी और सेट सदस्य के रूप में प्रयोग करने योग्य बनाता है, क्योंकि ये डेटा संरचनाएँ हैश मान का आंतरिक रूप से उपयोग करती हैं।

पाइथन की सभी अपरिवर्तनीय निर्मित वस्तुएँ धुलाई योग्य होती हैं, जबकि कोई भी उत्परिवर्तित कंटेनर (जैसे सूचियाँ या शब्दकोष) नहीं होते हैं। ऑब्जेक्ट जो उपयोगकर्ता द्वारा परिभाषित वर्गों के उदाहरण हैं वे डिफ़ॉल्ट रूप से धोने योग्य हैं; वे सभी असमान की तुलना करते हैं, और उनका हैश मान है id()


2
अगर यह hash valueअब हैश मान है। क्या आप कुछ उदाहरण दे सकते हैं
user1755071

2
@ user55711: यहां, हैश वैल्यू कॉलिंग का परिणाम है __hash__()। अधिक सामान्यतः, en.wikipedia.org/wiki/Hash_function
NPE

16
@TorstenBronger: क्योंकि दो असमान वस्तुएं एक ही मूल्य पर हैश कर सकती हैं। दूसरे शब्दों में, हैशिंग हानिकारक है।
NPE

1
अजगर-2.7.12 में, का परिणाम id(object)16x है object.__hash__()। तो इस संस्करण के लिए शब्दावली अंश गलत है - हैश मान नहीं है id(), लेकिन यह उससे प्राप्त होता है (जैसा कि वास्तव में अजगर 2.7.12 के लिए अद्यतन डॉक्स में उल्लेख किया गया है)।
दाविडा

2
मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन यह ध्यान देने योग्य है कि यहाँ कॉपी की जाने वाली प्रविष्टि पूरी तरह से सही नहीं है। आप एक ट्यूल के अंदर एक उत्परिवर्तित वस्तु (सूची की तरह) रख सकते हैं। टपल अभी भी अपरिवर्तनीय है, लेकिन आप इसके अंदर सूची को बदल सकते हैं, इसलिए यह उपलब्ध नहीं है। hash((1, [2, 3]))इसे कार्रवाई में देखने का प्रयास करें । मैंने हैश के लिए शब्दावली प्रविष्टि को सही करने के लिए एक अनुरोध पोस्ट किया है।
जॉन रिहाल

102

यहां सभी जवाबों में अजगर की हैशटैग वस्तुओं की अच्छी तरह से व्याख्या की गई है, लेकिन मेरा मानना ​​है कि पहले हाशिंग शब्द को समझने की जरूरत है।

हैशिंग कंप्यूटर विज्ञान में एक अवधारणा है जिसका उपयोग उच्च प्रदर्शन, छद्म यादृच्छिक अभिगम डेटा संरचनाओं को बनाने के लिए किया जाता है जहां बड़ी मात्रा में डेटा संग्रहीत और जल्दी से पहुँचा जा सकता है।

उदाहरण के लिए, यदि आपके पास 10,000 फ़ोन नंबर हैं, और आप उन्हें एक सरणी में संग्रहीत करना चाहते हैं (जो अनुक्रमिक डेटा संरचना है, जो सन्निहित स्मृति स्थानों में डेटा संग्रहीत करता है, और यादृच्छिक अभिगम प्रदान करता है), लेकिन आपके पास आवश्यक मात्रा में सन्निहित नहीं हो सकता है स्मृति स्थान।

तो, आप इसके बजाय आकार 100 की एक सरणी का उपयोग कर सकते हैं, और समान सूचकांकों के लिए मानों के एक सेट को मैप करने के लिए हैश फ़ंक्शन का उपयोग कर सकते हैं, और इन मानों को एक लिंक की गई सूची में संग्रहीत किया जा सकता है। यह एक सरणी के समान प्रदर्शन प्रदान करता है।

अब, एक हैश फ़ंक्शन सरणी के आकार के साथ संख्या को विभाजित करने और सूचकांक के रूप में शेष लेने के रूप में सरल हो सकता है।

अधिक विवरण के लिए https://en.wikipedia.org/wiki/Hash_function का संदर्भ लें

यहाँ एक और अच्छा संदर्भ है: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hun.html


1
यह हैशिंग पर एक दिलचस्प दृष्टिकोण है। मैंने इसके बारे में उस तरह से नहीं सोचा है।
युवागिन

@yuvgin हैश-टेबल अक्सर विरल-सरणियों (यानी यहां दिए गए उदाहरण) को लागू करने के लिए उपयोग किया जाता है।
एली कोरविगो

@EliKorvigo मुझे नियमित सरणियों के बारे में सोचना पसंद है जैसे कि हैश तालिका के अत्यधिक अनुकूलित संस्करण।
मार्क रैनसम

1
क्या आप हैशिंग की अवधारणा को स्पष्ट करने के लिए फ़ोन नंबर सरणी परिदृश्य के बारे में कुछ सरल कोड का उत्पादन कर सकते हैं?
इस्तियाक अहमद

18

कुछ भी जो उत्परिवर्तनीय नहीं है (उत्परिवर्तित साधन, बदलने की संभावना) हैशेड हो सकता है। देखने के लिए हैश फ़ंक्शन के अलावा, यदि किसी वर्ग के पास यह है, उदाहरण के लिए। dir(tuple)और __hash__विधि की तलाश में, यहाँ कुछ उदाहरण हैं

#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable

अपरिवर्तनीय प्रकारों की सूची:

int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes

परिवर्तनशील प्रकारों की सूची:

list, dict, set, bytearray, user-defined classes

मुझे हाल ही में पता चला कि Ellipsisयह एक अपरिवर्तनीय प्रकार भी है और इसे एक कुंजी के रूप में इस्तेमाल किया जा सकता है dict
गैबरे फेकेटे

यहां तक ​​कि उपयोगकर्ता-परिभाषित कक्षाएं भी इस्तेमाल की जा सकती हैं, लेकिन केवल उनके नाम ही उदाहरण नहीं हैं। जैसे:hash(MyClass)
गैबेर फेकेते

1
@ उपयोगकर्ता परिभाषित वर्गों के GáborFekete उदाहरण हैं यदि उनकी कक्षाएं लागू होती हैं __hash__और __eq__। इसके अलावा, सभी उपयोगकर्ता-परिभाषित वर्ग इन तरीकों को लागू करते हैं (और इस तरह से धो सकते हैं), क्योंकि वे object(सार्वभौमिक आधार-वर्ग) से विधियों को विरासत में लेते हैं ।
एली कोरविगो

7

पायथन शब्दावली के अनुसार मेरी समझ में, जब आप ऐसी वस्तुओं का एक उदाहरण बनाते हैं जो कि धुलाई योग्य होती हैं, तो एक अपरिवर्तनीय मूल्य की गणना उदाहरण के सदस्यों या मूल्यों के अनुसार भी की जाती है। उदाहरण के लिए, उस मूल्य को तब एक कुंजी के रूप में नीचे के रूप में इस्तेमाल किया जा सकता है:

>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c)  # a and c same object?
False
>>> a.__hash__() == c.__hash__()  # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'

हम पा सकते हैं कि tuple_a और tuple_c का हैश मान एक ही है क्योंकि उनके सदस्य समान हैं। जब हम ताना_ ए में कुंजी के रूप में tuple_a का उपयोग करते हैं, तो हम पा सकते हैं कि dict_a [tuple_c] के लिए मूल्य एक ही है, जिसका अर्थ है कि, जब वे एक तानाशाह की कुंजी के रूप में उपयोग किए जाते हैं, तो वे उसी मूल्य को वापस करते हैं क्योंकि हैश मान हैं वही। उन वस्तुओं के लिए जो धोए नहीं हैं, विधि हैश को किसी के रूप में परिभाषित नहीं किया गया है:

>>> type(dict.__hash__) 
<class 'NoneType'>

मुझे लगता है कि यह हैश मूल्य इंस्टेंस के गणना पर गणना की जाती है, न कि एक गतिशील तरीके से, इसीलिए केवल अपरिवर्तनीय वस्तुएं धोने योग्य होती हैं। उम्मीद है की यह मदद करेगा।


4

अजगर में धोए जाने योग्य वस्तुओं को समझने के लिए आपको एक उदाहरण देता हूं। मैं इस उदाहरण के लिए 2 टुपल्स ले रहा हूं। टपल में प्रत्येक मूल्य का एक विशिष्ट हैश मूल्य है जो अपने जीवनकाल के दौरान कभी नहीं बदलता है। तो इसके आधार पर मूल्य है, दो ट्यूपल्स के बीच तुलना की जाती है। हम Id () का उपयोग करके टुपल तत्व के हैश मान प्राप्त कर सकते हैं।

2 टुपल्स के बीच तुलना2 ट्यूपल के बीच समानता


26
यह छवि के बजाय पाठ के रूप में अधिक उपयोगी होगा
baxx

7
यह गलत उत्तर है। आईडी () एक मेमोरी में संदर्भित पता दिखाता है, यह एक हैश मान नहीं है। हैश का उपयोग करने के लिए __hash __ () फ़ंक्शन का उपयोग करें। उदाहरण: t1 .__ हैश __ ()
व्लाद

@ascentman आपके द्वारा गलत माना गया उत्तर संपादित करने में संकोच न करें। आपका संपादन सहकर्मी-समीक्षित होगा और यदि इसे स्वीकार कर लिया जाता है, तो आपको इसके लिए एक छोटा स्कोर इनाम मिलता है।
XavierStuvw

4

अजगर में इसका मतलब है कि वस्तु एक सूचकांक वापस करने के लिए सेट के सदस्य हो सकते हैं। यानी उनकी विशिष्ट पहचान / आईडी है।

उदाहरण के लिए, अजगर 3.3 में:

डेटा संरचना सूचियाँ उपलब्ध नहीं हैं, लेकिन डेटा संरचना Tuples उपलब्ध नहीं हैं।


हैश समान नहीं है id, जो कि (लगभग) मेमोरी में ऑब्जेक्ट का पता है।
पूल डे

3

हशेबल = हैशेड होने में सक्षम।

ठीक है, हैशिंग क्या है? एक हैशिंग फ़ंक्शन एक फ़ंक्शन है जो ऑब्जेक्ट लेता है, "पायथन" जैसे एक स्ट्रिंग कहता है और एक निश्चित आकार का कोड देता है। सादगी के लिए, मान मान रिटर्न पूर्णांक है।

जब मैं पायथन 3 में हैश ('पायथन') चलाता हूं, तो मुझे परिणाम के रूप में 5952713340227947791 मिलते हैं। पायथन के विभिन्न संस्करण अंतर्निहित हैश फ़ंक्शन को बदलने के लिए स्वतंत्र हैं, इसलिए आपको संभवतः एक अलग मूल्य मिलेगा। महत्वपूर्ण बात यह है कि अब कोई बात नहीं कई बार मैं हैश ('पायथन') चलाता हूं, मैं हमेशा पायथन के समान संस्करण के साथ एक ही परिणाम प्राप्त करूंगा।

लेकिन हैश ('जावा') 1753925553814008565 पर वापस लौटता है। इसलिए यदि मैं जिस ऑब्जेक्ट में हैशिंग बदल रहा हूं, तो वह परिणाम करता है। दूसरी ओर, यदि मैं हैशिंग वाला ऑब्जेक्ट नहीं बदलता है, तो परिणाम वही रहता है।

यह बात क्यों है?

उदाहरण के लिए, पायथन डिक्शनरी में, चाबियाँ अपरिवर्तनीय होने की आवश्यकता होती है। यही है, चाबियाँ ऐसी वस्तुएं होनी चाहिए जो बदलती नहीं हैं। पायथन में स्ट्रिंग्स अपरिवर्तनीय हैं, जैसे कि अन्य बुनियादी प्रकार (इंट, फ्लोट, बूल) हैं। टुपल्स और फ्रोजेनसेट भी अपरिवर्तनीय हैं। दूसरी ओर, सूचियाँ अपरिवर्तनीय नहीं होती हैं (अर्थात, वे परिवर्तनशील हैं) क्योंकि आप उन्हें बदल सकते हैं। इसी तरह, dicts परस्पर हैं।

इसलिए जब हम कहते हैं कि कोई चीज धोने योग्य है, तो हमारा मतलब है कि यह अपरिवर्तनीय है। अगर मैं हैश () फ़ंक्शन में एक परिवर्तनशील प्रकार पास करने की कोशिश करता हूं, तो यह विफल हो जाएगा:

>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656

1
ध्यान दें कि अजगर प्रत्येक प्रक्रिया की शुरुआत में बेतरतीब ढंग से हैशिंग एल्गोरिथ्म को बीज देता है। इसलिए, यदि आप अलग-अलग प्रक्रियाओं में दो बार हैश ('पायथन') चलाते हैं, तो आपको वास्तव में अलग-अलग हैश मान मिलेंगे।
डी हडसन

2

पायथन में, कोई भी अपरिवर्तनीय वस्तु (जैसे एक पूर्णांक, बूलियन, स्ट्रिंग, ट्यूपल) धोने योग्य है, जिसका अर्थ है कि जीवनकाल के दौरान इसका मूल्य नहीं बदलता है। यह पायथन को इसकी पहचान करने के लिए एक अद्वितीय हैश मान बनाने की अनुमति देता है, जिसका उपयोग अद्वितीय कुंजियों को ट्रैक करने के लिए शब्दकोशों द्वारा किया जा सकता है और अद्वितीय मूल्यों को ट्रैक करने के लिए सेट किया जा सकता है।

यही कारण है कि पायथन को हमें एक शब्दकोश में कुंजियों के लिए अपरिवर्तनीय डेटाटिप्स का उपयोग करने की आवश्यकता होती है।


-1

खरोंच से एक हैशिंग तालिका बनाने के लिए, सभी मानों को "कोई नहीं" पर सेट करना पड़ता है और एक बार आवश्यकता होने पर संशोधित किया जाता है। हशेबल ऑब्जेक्ट्स मॉडिफाइबल डेटाैटिप्स (डिक्शनरी, लिस्ट आदि) को संदर्भित करता है। दूसरी ओर सेट को एक बार सौंपे जाने के बाद पुनर्निमित नहीं किया जा सकता है, इसलिए सेट गैर-धोने योग्य होते हैं। जबकि, द वेरिएंट ऑफ़ सेट () - फ्रोज़ेन्सेट () - हैज़ेबल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.