সম্পাদনা : আপনার সমস্ত কী যদি স্ট্রিং হয় , তবে এই উত্তরটি পড়া চালিয়ে যাওয়ার আগে দয়া করে জ্যাক ও'কনোরের উল্লেখযোগ্য সরল (এবং দ্রুত) সমাধানটি দেখুন (যা নেস্টেড অভিধানগুলি হ্যাশিংয়ের জন্যও কাজ করে)।
যদিও একটি উত্তর গৃহীত হয়েছে, তথাপি প্রশ্নের শিরোনাম হ্যাশিং একটি অজগর অভিধান, এবং সেই শিরোনামটি সম্পর্কে উত্তরটি অসম্পূর্ণ। (প্রশ্নের প্রধান হিসাবে, উত্তরটি সম্পূর্ণ is
নেস্টেড ডিকশনারি
যদি কোনও অভিধান কীভাবে হ্যাশ করতে হয় তার জন্য স্ট্যাক ওভারফ্রো অনুসন্ধান করে, কেউ এই উপযুক্তভাবে শিরোনামযুক্ত প্রশ্নের উপর ঝুঁকতে পারে এবং কেউ যদি নেস্টেড ডিকশনারি হ্যাশ করার চেষ্টা করে তবে অসন্তুষ্ট থাকে। উপরের উত্তরটি এই ক্ষেত্রে কাজ করবে না এবং হ্যাশটি পুনরুদ্ধার করতে আপনাকে এক ধরণের পুনরাবৃত্তিমূলক ব্যবস্থা প্রয়োগ করতে হবে।
এখানে একটি যেমন প্রক্রিয়া:
import copy
def make_hash(o):
"""
Makes a hash from a dictionary, list, tuple or set to any level, that contains
only other hashable types (including any lists, tuples, sets, and
dictionaries).
"""
if isinstance(o, (set, tuple, list)):
return tuple([make_hash(e) for e in o])
elif not isinstance(o, dict):
return hash(o)
new_o = copy.deepcopy(o)
for k, v in new_o.items():
new_o[k] = make_hash(v)
return hash(tuple(frozenset(sorted(new_o.items()))))
বোনাস: হ্যাশিং অবজেক্টস এবং ক্লাসেস
hash()
ফাংশন কাজ করে মহান যখন আপনি শ্রেণীর বা দৃষ্টান্ত হ্যাশ। যাইহোক, হ্যাশের সাথে আমি খুঁজে পেয়েছি এমন একটি বিষয়, যা বস্তু সম্পর্কিত:
class Foo(object): pass
foo = Foo()
print (hash(foo)) # 1209812346789
foo.a = 1
print (hash(foo)) # 1209812346789
হুশ একই, এমনকি আমি ফু বদলেছি। এটি কারণ ফু এর পরিচয় পরিবর্তন হয়নি, তাই হ্যাশটি একই। যদি আপনি foo এর বর্তমান সংজ্ঞা অনুসারে আলাদাভাবে হ্যাশ করতে চান তবে সমাধানটি হ'ল যা কিছু পরিবর্তন করছে তা হ্যাশ করে দেওয়া। এই ক্ষেত্রে, __dict__
বৈশিষ্ট্য:
class Foo(object): pass
foo = Foo()
print (make_hash(foo.__dict__)) # 1209812346789
foo.a = 1
print (make_hash(foo.__dict__)) # -78956430974785
হায়, আপনি যখন ক্লাসে নিজেই একই জিনিসটি করার চেষ্টা করছেন:
print (make_hash(Foo.__dict__)) # TypeError: unhashable type: 'dict_proxy'
শ্রেণীর __dict__
সম্পত্তিটি কোনও সাধারণ অভিধান নয়:
print (type(Foo.__dict__)) # type <'dict_proxy'>
এখানে পূর্বের মতো একই ব্যবস্থা রয়েছে যা ক্লাসগুলি যথাযথভাবে পরিচালনা করবে:
import copy
DictProxyType = type(object.__dict__)
def make_hash(o):
"""
Makes a hash from a dictionary, list, tuple or set to any level, that
contains only other hashable types (including any lists, tuples, sets, and
dictionaries). In the case where other kinds of objects (like classes) need
to be hashed, pass in a collection of object attributes that are pertinent.
For example, a class can be hashed in this fashion:
make_hash([cls.__dict__, cls.__name__])
A function can be hashed like so:
make_hash([fn.__dict__, fn.__code__])
"""
if type(o) == DictProxyType:
o2 = {}
for k, v in o.items():
if not k.startswith("__"):
o2[k] = v
o = o2
if isinstance(o, (set, tuple, list)):
return tuple([make_hash(e) for e in o])
elif not isinstance(o, dict):
return hash(o)
new_o = copy.deepcopy(o)
for k, v in new_o.items():
new_o[k] = make_hash(v)
return hash(tuple(frozenset(sorted(new_o.items()))))
আপনি এটি চাইলেও অনেকগুলি উপাদানগুলির একটি হ্যাশ টুপল ফিরে পেতে আপনি এটি ব্যবহার করতে পারেন:
# -7666086133114527897
print (make_hash(func.__code__))
# (-7666086133114527897, 3527539)
print (make_hash([func.__code__, func.__dict__]))
# (-7666086133114527897, 3527539, -509551383349783210)
print (make_hash([func.__code__, func.__dict__, func.__name__]))
দ্রষ্টব্য: উপরের সমস্ত কোড পাইথন 3.x ধরে নিয়েছে। পূর্ববর্তী সংস্করণগুলিতে পরীক্ষা করা হয়নি, যদিও আমি অনুমান করি যে make_hash()
এটি কাজ করবে, বলুন, ২.7.২। যতদূর উদাহরণগুলি কাজ করে, আমি এটি জানি
func.__code__
সঙ্গে প্রতিস্থাপন করা উচিত
func.func_code