अजगर में हैश क्या करता है?


86

मैंने कोड का एक उदाहरण देखा कि जहां hashकार्य एक ट्यूपल पर लागू होता है। परिणामस्वरूप यह एक नकारात्मक पूर्णांक देता है। मुझे आश्चर्य है कि यह कार्य क्या करता है? Google मदद नहीं करता है। मुझे एक पृष्ठ मिला जिसमें बताया गया है कि हैश की गणना कैसे की जाती है लेकिन यह स्पष्ट नहीं करता है कि हमें इस फ़ंक्शन की आवश्यकता क्यों है।



इस लिंक (आधिकारिक दस्तावेज) पर जाएं। यह सब कुछ निर्दिष्ट करता है। पर जाने के लिंक !
दर्जी_राज

2
मुझे पसंद है कि प्रश्न "क्या है" का दोहराव नहीं है, लेकिन "हमें इसकी आवश्यकता क्यों है"।
dnozay

आधिकारिक लिंक बहुत भ्रामक है
रश्मि रंजन नायक

जवाबों:


148

हैश एक निश्चित आकार का पूर्णांक है जो किसी विशेष मान की पहचान करता है । प्रत्येक मान का अपना हैश होना आवश्यक है, इसलिए समान मूल्य के लिए भी आपको वही हैश मिलेगा, भले ही वह समान वस्तु न हो।

>>> hash("Look at me!")
4343814758193556824
>>> f = "Look at me!"
>>> hash(f)
4343814758193556824

हैश मानों को इस तरह से बनाने की आवश्यकता है कि परिणामी मान समान रूप से आपके द्वारा प्राप्त होने वाले हैश टकरावों की संख्या को कम करने के लिए वितरित किए जाते हैं। हैश टकराव तब होता है जब दो अलग-अलग मूल्यों में एक ही हैश होता है। इसलिए, अपेक्षाकृत छोटे परिवर्तन अक्सर बहुत अलग हैश में होते हैं।

>>> hash("Look at me!!")
6941904779894686356

ये संख्याएँ बहुत उपयोगी हैं, क्योंकि वे मूल्यों के एक बड़े संग्रह में मूल्यों के त्वरित लुक-अप को सक्षम करती हैं। उनके उपयोग के दो उदाहरण पायथन के हैं setऔर dict। ए में list, यदि आप जांचना चाहते हैं कि क्या मूल्य सूची में है, तो if x in values:, पायथन को पूरी सूची में जाने की जरूरत है और सूची में xप्रत्येक मूल्य की तुलना करें values। इसमें लंबा समय लग सकता है list। एक में set, पायथन प्रत्येक हैश का ट्रैक रखता है, और जब आप टाइप करते हैं if x in values:, तो पायथन के लिए हैश-मूल्य मिलेगा x, एक आंतरिक संरचना में देखें और फिर xउन मूल्यों की तुलना करें जिनके पास समान हैश है x

शब्दकोश देखने के लिए उसी पद्धति का उपयोग किया जाता है। इस में देखने में आता है setऔर dictबहुत तेजी से है, जबकि में देखने listधीमी है। इसका मतलब यह भी है कि आपके पास गैर-धोने योग्य ऑब्जेक्ट हो सकते हैं list, लेकिन ए में setया के रूप में नहीं dict। गैर-धोने योग्य वस्तुओं का विशिष्ट उदाहरण कोई भी वस्तु है जो परस्पर है, जिसका अर्थ है कि आप इसके मूल्य को बदल सकते हैं। यदि आपके पास एक उत्परिवर्तनीय वस्तु है, तो इसे धोए नहीं जाना चाहिए, क्योंकि इसका हैश तब अपने जीवन-समय में बदल जाएगा, जिससे बहुत भ्रम हो जाएगा, क्योंकि कोई वस्तु किसी शब्दकोश में गलत हैश मान के तहत समाप्त हो सकती है।

ध्यान दें कि मूल्य का हैश केवल पायथन के एक रन के लिए समान होना चाहिए। पायथन 3.3 में वे वास्तव में पायथन के हर नए रन के लिए बदलाव करेंगे:

$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
1849024199686380661
>>> 
$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
-7416743951976404299

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

हैश मान इसलिए स्थायी रूप से संग्रहीत नहीं किया जाना चाहिए। यदि आपको स्थायी रूप से हैश मानों का उपयोग करने की आवश्यकता है, तो आप अधिक "गंभीर" प्रकार के हैश, क्रिप्टोग्राफ़िक हैश फ़ंक्शंस पर नज़र डाल सकते हैं , जिनका उपयोग फ़ाइलों के सत्यापन योग्य चेकसम आदि बनाने के लिए किया जा सकता है।


11
संभावित हैश टकराव के बारे में: hash(-1) == hash(-2)(रनिन पायथन 2.7)
मथायस

2
मैं पायथन 3.6.1 चला रहा हूं और टक्कर मौजूद है।
the_Martian

hash(-1) == hash(-2)आज भी मौजूद है। सौभाग्य से, यह शब्दकोश और सेट लुकअप पर प्रतिकूल प्रभाव नहीं डालता है। अन्य सभी पूर्णांकों iको hash(i)छोड़कर खुद के लिए हल करते हैं -1
क्रिस कॉनन जूल

35

टी एल; डॉ:

कृपया शब्दकोष का संदर्भ लें : hash()वस्तुओं की तुलना करने के लिए एक शॉर्टकट के रूप में उपयोग किया जाता है, यदि किसी वस्तु को अन्य वस्तुओं की तुलना में धोया जा सकता है। यही कारण है कि हम उपयोग करते हैं hash()। इसका उपयोग उन तत्वों dictऔर setउपयोगों के लिए भी किया जाता है जिन्हें CPython में resizable हैश टेबल के रूप में कार्यान्वित किया जाता है ।

तकनीकी विचार

  • आमतौर पर वस्तुओं की तुलना करना (जिसमें कई स्तरों की पुनरावृत्ति शामिल हो सकती है) महंगी होती है।
  • अधिमानतः, hash()फ़ंक्शन कम मात्रा में परिमाण (या कई) का एक आदेश है।
  • दो हैश की तुलना दो वस्तुओं की तुलना में आसान है, यह वह जगह है जहां शॉर्टकट है।

यदि आप इस बारे में पढ़ते हैं कि शब्दकोशों को कैसे लागू किया जाता है , तो वे हैश टेबल का उपयोग करते हैं, जिसका अर्थ है कि ऑब्जेक्ट से एक कुंजी प्राप्त करना, शब्दकोशों में वस्तुओं को पुनः प्राप्त करने के लिए एक कोने का पत्थर है O(1)। हालांकि यह टक्कर-प्रतिरोधी होने के लिए आपके हैश फ़ंक्शन पर बहुत निर्भर है । एक आइटम प्राप्त करने के लिए सबसे खराब स्थिति एक शब्दकोश में वास्तव में है O(n)

उस नोट पर, उत्परिवर्तनीय वस्तुएं आमतौर पर धोने योग्य नहीं होती हैं। धोने योग्य संपत्ति का मतलब है कि आप एक कुंजी के रूप में एक वस्तु का उपयोग कर सकते हैं। यदि हैश मान एक कुंजी के रूप में उपयोग किया जाता है और उसी वस्तु की सामग्री बदल जाती है, तो हैश फ़ंक्शन क्या लौटना चाहिए? यह एक ही कुंजी या एक अलग है? यह इस बात पर निर्भर करता है कि आप अपने हैश फ़ंक्शन को कैसे परिभाषित करते हैं।

उदाहरण से सीखना:

कल्पना कीजिए कि हमारे पास यह वर्ग है:

>>> class Person(object):
...     def __init__(self, name, ssn, address):
...         self.name = name
...         self.ssn = ssn
...         self.address = address
...     def __hash__(self):
...         return hash(self.ssn)
...     def __eq__(self, other):
...         return self.ssn == other.ssn
... 

कृपया ध्यान दें: यह सब इस धारणा पर आधारित है कि SSN किसी व्यक्ति के लिए कभी नहीं बदलता (यह भी नहीं पता कि वास्तव में आधिकारिक स्रोत से उस तथ्य को कहां सत्यापित किया जाए)।

और हमारे पास बॉब है:

>>> bob = Person('bob', '1111-222-333', None)

बॉब अपना नाम बदलने के लिए एक न्यायाधीश को देखने जाता है:

>>> jim = Person('jim bo', '1111-222-333', 'sf bay area')

यह हम जानते हैं:

>>> bob == jim
True

लेकिन ये दो अलग-अलग ऑब्जेक्ट हैं जो अलग-अलग मेमोरी आवंटित करते हैं, जैसे एक ही व्यक्ति के दो अलग-अलग रिकॉर्ड:

>>> bob is jim
False

अब वह हिस्सा आता है जहाँ हैश () काम है:

>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'

अंदाज़ा लगाओ:

>>> dmv_appointments[jim] #?
'tomorrow'

दो अलग-अलग रिकॉर्ड्स से आप एक ही जानकारी हासिल कर सकते हैं। अब यह प्रयास करें:

>>> dmv_appointments[hash(jim)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in __eq__
AttributeError: 'int' object has no attribute 'ssn'
>>> hash(jim) == hash(hash(jim))
True

अभी क्या हुआ? वह टक्कर है। क्योंकि hash(jim) == hash(hash(jim))जो दोनों पूर्णांक btw हैं, हमें __getitem__उन सभी वस्तुओं के इनपुट की तुलना करने की आवश्यकता है जो टकराते हैं। बिलिन intमें एक ssnविशेषता नहीं है इसलिए यह यात्रा करता है।

>>> del Person.__eq__
>>> dmv_appointments[bob]
'tomorrow'
>>> dmv_appointments[jim]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: <__main__.Person object at 0x7f611bd37110>

इस अंतिम उदाहरण में, मैं बताता हूं कि टक्कर के साथ भी, तुलना की जाती है, वस्तुएं अब समान नहीं हैं, जिसका अर्थ है कि यह सफलतापूर्वक एक है KeyError


वास्तव में आसान व्याख्या। नौसिखिए के रूप में, इससे मुझे यह पता लगाने में मदद मिली कि कक्षा कैसे बनाई जाए जो सेट में रखी जाए और उन्हें शब्दकोश / हैश तालिका के लिए कुंजियों के रूप में उपयोग किया जाए। अगर मैं संग्रह [hashable_obj] = hashable_obj करता हूं, तो मुझे बाद में उस उदाहरण के लिए एक संकेतक मिल सकता है। लेकिन मुझे बताएं कि क्या इस तरह के संग्रह का ट्रैक रखने का एक बेहतर तरीका है।
पॉलडोंग

@dnozay लेकिन, फिर भी, आउटपुट hash()एक निश्चित आकार का पूर्णांक है, जो टक्कर का कारण बन सकता है
ओवरएक्सचेंज

2
क्या कोई __eq__उपरोक्त उदाहरण के उपयोग के बारे में विस्तार से बता सकता है । क्या यह शब्दकोष द्वारा बुलाया जाता है जब यह उस कुंजी की तुलना करने की कोशिश कर रहा है जो इसे प्राप्त सभी कुंजियों के साथ है? इस तरह की है कि द्वारा पिछले उदाहरण में विधि, शब्दकोश कुंजी यह कुंजी यह है के साथ प्राप्त हुआ है की समानक निर्धारित करने के लिए उपयोग करने के लिए कॉल करने के लिए कुछ भी नहीं है? del__eq__
जेट ब्लू

1
@JetBlue "कोलाज" स्पष्टीकरण कुंजी के साथ उदाहरण में अधूरा है hash(jim)Person.__eq__कहा जाता है क्योंकि मौजूदा कुंजी के पास यह hash(jim)सुनिश्चित करने के लिए एक ही हैश है कि यह सही कुंजी Person.__eq__का उपयोग किया जाता है। यह गलत है क्योंकि यह मानता है कि other, जो intएक ssnविशेषता है। यदि hash(jim)कुंजी शब्दकोश में मौजूद नहीं है, तो __eq__उसे कॉल नहीं किया जाएगा। यह बताता है कि जब कुंजी लुकिंग O (n) हो सकता है: जब सभी वस्तुओं में समान हैश __eq__का उपयोग उन सभी पर किया जाना चाहिए, उदाहरण के लिए जब कुंजी मौजूद नहीं है।
वलहु

1
हालाँकि, मैं आपके उदाहरण के शैक्षणिक हित को समझता हूँ, क्या इसे केवल dmv_appointments[bob.ssn] = 'tomorrow'एक __hash__विधि को परिभाषित करने की आवश्यकता को हटाते हुए, लिखना आसान नहीं होगा ? मैं समझता हूं कि आपके द्वारा लिखे और पढ़े जाने वाले प्रत्येक अपॉइंटमेंट के लिए 4 वर्ण जोड़े गए हैं, लेकिन यह मुझे स्पष्ट लगता है।
एलेक्सिस

3

राज्य के लिएhash() अजगर डॉक्स :

हैश मान पूर्णांक हैं। शब्दकोश लुकअप के दौरान शब्दकोश कुंजियों की तुलना करने के लिए उनका उपयोग किया जाता है।

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

इसके अतिरिक्त, प्रकार राज्य के लिए डॉक्सdict :

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


1

हैश का उपयोग शब्दकोशों द्वारा किया जाता है और ऑब्जेक्ट को जल्दी से देखने के लिए सेट करता है। हैश टेबल पर एक अच्छा प्रारंभिक बिंदु विकिपीडिया का लेख है ।


-2

आप Dictionaryअजगर में डेटा प्रकार का उपयोग कर सकते हैं । यह बहुत हद तक हैश की तरह है - और यह नेस्टिंग हैश के समान, नेस्टिंग का भी समर्थन करता है।

उदाहरण:

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School" # Add new entry

print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])

अधिक जानकारी के लिए, कृपया इस ट्यूटोरियल को डिक्शनरी डेटा टाइप पर देखें

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