অজগরে হ্যাশ কী করে?


88

আমি কোডের একটি উদাহরণ দেখেছি যেখানে hashফাংশনটি একটি টিউপলে প্রয়োগ করা হয়। ফলস্বরূপ এটি একটি নেতিবাচক পূর্ণসংখ্যার ফেরত দেয়। আমি ভাবছি এই ফাংশনটি কী করে? গুগল সাহায্য করে না। আমি একটি পৃষ্ঠা পেয়েছি যা ব্যাখ্যা করে যে কীভাবে হ্যাশ গণনা করা হচ্ছে তবে এটি কেন আমাদের এই ফাংশনটির প্রয়োজন তা ব্যাখ্যা করে না।



এই লিঙ্কে যান (অফিসিয়াল ডকুমেন্টেশন)। এটি সবকিছু নির্দিষ্ট করে। লিঙ্ক যেতে !
দর্জি_রাজ

4
আমি পছন্দ করি যে প্রশ্নটি "এটি কী" এর পুনরাবৃত্তি নয়, তবে "কেন আমাদের এটি প্রয়োজন"।
dnozay

অফিসিয়াল লিঙ্কটি খুব বিভ্রান্তিকর
রাসমি রঞ্জন নায়ক

উত্তর:


156

একটি হ্যাশ একটি নির্দিষ্ট আকারের পূর্ণসংখ্যা যা একটি নির্দিষ্ট মান সনাক্ত করে । প্রতিটি মানটির নিজস্ব হ্যাশ থাকা দরকার, সুতরাং একই মানের জন্য আপনি একই হ্যাশ পাবেন যদিও এটি একই জিনিস নয়।

>>> 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নন । নন-হ্যাশেবল অবজেক্টের আদর্শ উদাহরণ হ'ল যে কোনও বস্তু যা পরিবর্তনীয়, যার অর্থ আপনি এর মান পরিবর্তন করতে পারেন। যদি আপনার কোনও পরিবর্তনীয় অবজেক্ট থাকে তবে এটি হ্যাশযোগ্য হওয়া উচিত নয়, কারণ এর হ্যাশটি তার জীবনকালকে পরিবর্তিত করবে, যা প্রচুর বিভ্রান্তির কারণ হতে পারে, কারণ কোনও অভিধানে কোনও অভিধানে ভুল হ্যাশ মানটির আওতায় আসতে পারে।setdict

মনে রাখবেন যে পাইথনের এক রান করার জন্য একটি মানের হ্যাশ একই হওয়া দরকার। পাইথন ৩.৩-এ তারা পাইথনের প্রতিটি নতুন রানের জন্য বাস্তবে পরিবর্তন ঘটবে:

$ /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

এটি তৈরি করা কোনও নির্দিষ্ট স্ট্রিংয়ের হ্যাশের মান কী তা ওয়েব অ্যাপ্লিকেশন ইত্যাদির জন্য একটি গুরুত্বপূর্ণ সুরক্ষা বৈশিষ্ট্য hard

হ্যাশ মানগুলি স্থায়ীভাবে সংরক্ষণ করা উচিত নয়। যদি আপনাকে স্থায়ীভাবে হ্যাশ মানগুলি ব্যবহার করতে হয় তবে আপনি আরও "গুরুতর" ধরণের হ্যাশগুলি, ক্রিপ্টোগ্রাফিক হ্যাশ ফাংশনগুলি দেখে নিতে পারেন, যা ফাইলগুলির যাচাইযোগ্য চেকসাম ইত্যাদির জন্য ব্যবহার করা যেতে পারে etc.


12
সম্ভাব্য হ্যাশ সংঘর্ষ সম্পর্কিত: hash(-1) == hash(-2)(রান্নিন পাইথন ২.7)
ম্যাথিয়াস

4
আমি পাইথন 3.6.1 চালাচ্ছি এবং সংঘর্ষের উপস্থিতি রয়েছে।
দ্য_মার্টিয়ান

hash(-1) == hash(-2)এখনও বিদ্যমান। ভাগ্যক্রমে, এটি অভিধানে এবং সেট লকআপগুলিকে বিরূপ প্রভাবিত করে না। অন্যান্য সমস্ত পূর্ণসংখ্যার ব্যতীত iনিজেদের মধ্যে সংকল্প করে । hash(i)-1
ক্রিস কনলান

36

টিএল; ডিআর:

দয়া করে পড়ুন শব্দকোষ : hash()বস্তু তুলনা একটি শর্টকাট হিসাবে ব্যবহার করা হয়, একটি অবজেক্ট hashable বলিয়া গণ্য যদি এটা অন্যান্য বস্তুর তুলনা করা যেতে পারে করা হয়। এজন্যই আমরা ব্যবহার করি hash()। এটি অ্যাক্সেস করতে dictএবং setউপাদানগুলিকে ব্যবহার করা হয় যা সিপিথনে পুনরায় আকার পরিবর্তনযোগ্য হ্যাশ টেবিল হিসাবে প্রয়োগ করা হয় ।

প্রযুক্তিগত বিবেচনা

  • সাধারণত বস্তুর তুলনা করা (যা বিভিন্ন স্তরের পুনরাবৃত্তি জড়িত থাকতে পারে) ব্যয়বহুল।
  • সাধারণত, 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
... 

দয়া করে নোট করুন: এসএসএন কখনই কোনও ব্যক্তির জন্য পরিবর্তিত হয় না (এই বিষয়টি সত্যিকারের উত্স থেকে সত্য সত্য যাচাই করতে হবে তাও জানেন না) এই ধারণার উপর ভিত্তি করে।

এবং আমাদের বব আছে:

>>> 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>

এই শেষ উদাহরণে, আমি দেখাই যে সংঘর্ষের সাথেও তুলনাটি সম্পাদন করা হয়, বস্তুগুলি আর সমান হয় না, যার অর্থ এটি সফলভাবে উত্থাপন করে a KeyError


সত্যিই সহজ ব্যাখ্যা। নবাগত হিসাবে, এটি আমাকে কীভাবে শ্রেণি তৈরি করতে পারে সেগুলি নির্ধারণ করতে এবং অভিধান / হ্যাশ টেবিলের কী হিসাবে তাদের ব্যবহার করতে সহায়তা করে helped এছাড়াও যদি আমি [hashable_obj] = hashable_obj সংগ্রহ করি তবে আমি পরে সেই উদাহরণটিতে পয়েন্টার পেতে পারি। তবে এই জাতীয় সংগ্রহগুলি ট্র্যাক করার আরও ভাল উপায় আছে কিনা তা আমাকে বলুন।
পলডং

@ ডিএনজয়ে তবে, এখনও, hash()একটি স্থির আকারের পূর্ণসংখ্যার আউটপুট , এটি সংঘর্ষের কারণ হতে পারে
ওভার এক্সচেঞ্জ

4
কেউ কি __eq__উপরের উদাহরণটিতে ব্যবহারের বিষয়ে বিস্তারিত বলতে পারেন । অভিধানটি যখন এটি প্রাপ্ত কীগুলি এটির সাথে থাকা সমস্ত কীগুলির সাথে তুলনা করার চেষ্টা করা হয়? এই ধরনের যে গত উদাহরণে পদ্ধতি, অভিধান চাবি এটা কী এটা রয়েছে তার সাথে পেয়েছে এর সমানতা নির্ধারণ করতে ব্যবহার করতে কলে নেই? del__eq__
জেট ব্লু

4
@ জেটব্লিউ "সংঘাত" ব্যাখ্যা কী সহ উদাহরণটিতে অসম্পূর্ণ hash(jim)Person.__eq__বলা হয় কারণ বিদ্যমান কীটির একই হ্যাশ রয়েছে যা hash(jim)নিশ্চিত করতে পারে যে এটি সঠিক কীটি Person.__eq__ব্যবহৃত হয়েছে। এটা তোলে ভুল কারণ এটি ধরে নেয় যে other, যা int, একটি হয়েছে ssnঅ্যাট্রিবিউট। তাহলে hash(jim)কী অভিধানে উপস্থিত করেনি __eq__বলা হয় না হবে। কী বর্ণনাকে ও (এন) হতে পারে এটি এটি ব্যাখ্যা করে: যখন সমস্ত আইটেমের একই হ্যাশ থাকে __eq__সেগুলি অবশ্যই ব্যবহার করা উচিত, উদাহরণস্বরূপ যখন কী বিদ্যমান না থাকে।
WloHu

4
যদিও আমি আপনার উদাহরণের শিক্ষাগত আগ্রহটি বুঝতে পেরেছি, তবে কী 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'])

আরও তথ্যের জন্য, দয়া করে অভিধানের ডেটা টাইপের এই টিউটোরিয়ালটি উল্লেখ করুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.