tgoop.com/pythonlearnme/255
Last Update:
خب شاید پیش خودتون بگید، آبجکتی که داندر hash داشته باشه حتما hashable عه دیگه، این داندر رو داره و جوابتون این باشه:o = obj
خیر 😁
if hasattr(o, 'hash'):
print(f"{o} is hashable")
اما
اول یه چیز پایهای بگیم.
کلاس آبجکت object پایهای ترین base class در پایتونه و اینکه میگن همهچیز در پایتون آبجکته، یکی از دلیلاش اینه. هر چیزی که فکرش رو بکنید از object ارث میبره.
این کلاس کلی داندر متد داره و از قضا دو تا داندر که در این مطلب برای ما مهم هستن رو هم با هم داره
داندر eq -> برای چک کردن تساوی دو تا آبجکتobj1 == obj2
داندر hash -> برای برگرداندن مقدار hash آبجکت که از تابع hash میگیریمhash(obj)
وقتی یک کلاسی شما مینویسید:class Spam:
این کلاس به طور خودکار از کلاس آبجکت ارث میبره که تبعا داندر متدها براش resolve میشن، که یعنی، ارثشون میبره، یا اینکه میگرده توی کلاس object پیدا شون میکنه.
pass
نکتهی داندر eq
رفتار پیشفرض داندر eq به این صورته که میان آیدیهای دو آبجکت رو باهم مقایسه میکنه. یعنی اگه اون رو override نکرده باشید و بخواید آبجکتهاتون رو با هم مقایسه کنید، وقتی جواب True میگیرید که دو تا آبجکت در واقع یک آبجکت باشن. دقیقا همون کاری که is
انجام میده. s1 = s2 = Spam()
اما شاید چنین رفتاری رو نخواید و جور دیگهای بخوایید که آبجکتهای شما تساویشون چک بشه
s1 == s2 -> True
خب میاید داندر eq رو جوری که میخواید اورراید میکنید
اما 😁
وقتی این کار رو کردید، اتفاقی که میوفته اینه که مقدار داندر hash شما None میشه و آبجکت شما دیگه hashable نیست
این یعنی دیگه نمیتونید توی دیکشنری و ست بذاریدش و ....
این در حالیه که آبجکت شما همچنان داندر hash داره ولی hashable نیست.
این توضیحات میشن دلیل اینکه چرا اون شرط باگ داره.
اما راهحل چیه؟
خب شاید بیاید بگید بجای اینکه چک کنیم هست، چک میکنیم که None نباشهif o.hash is not None:
تا حدی مشکل رو حل میکنه اما از اونجایی که پایتون یه زبان به شدت داینامیک عه:
...
این class Spam:
هترین راهحل چیه؟
def eq ...
Spam.hash = "Gotcha, Im neither hashable nor None =)"
پس ب
It is easier to ask forgiveness than permission try:
اما یه سوال بی جواب میمونه!
hash(o)
except TypeError:
print("unhashable")
else:
print("hashable")
بالاتر گفتیم اگه داندر eq رو اورراید کنیم آبجکت ما دیگه hashable نیست و توی ست و دیکشنری نمیتونیم استفاده کنیم. من میخوام اون ور اورراید کنم و بازم hashable باشه 😒😒
خب جوابش سادهست
شما باید داندر hash رو هم اورراید کنید و یه مقدار int برگردونید
نکتهای که هست و باید بهش توجه داشته باشید اینه که باید بتونید یه عددی تولید کنید که تکراری شدنش سخت باشه (اگه تکراری بشه اشکالی نداره) و به ویژگیهای آبجکت شما وابسته هم باشه (حتما قرار نیست به ویژگیهاش وابسته باشه، اما اگه باشه، اون نکتهی قبلی راحتتر بدست میاد)
برای مثالclass Spam:
می مختلفی قراره به هر آبجکت که از Spam درست میکنید بدید، و این باعث میشه که hash هر بار فرق کنه
def init(self, name):
self.name = name
def eq(self):
....
def hash(self):
return hash(self.name)
تبعا شما اسا
اما اگه اسم یکسان هم بدید، مشکلی نیست یه قانونی هست توی بحث hash که میگه:
اگر دو آبجکت دقیقا یکسان باشن، (یعنی دو تا رفرنس از یک آبجکت رو داشته باشیم) باید hash یکسانی داشته باشن
اما اگر ما دو تا hash یکسان از دو تا آبجکت داشتیم، الزاما اون دو آبجکت یکی نیستن.
به این حالت که هش یکسانه ولی آبجکتا یکی نیستن، میگن hash collision. که پایتون خودش این رو هندل میکنه
و بحثش در این مقال "دیگر 😮💨" نمیگنجد.
موفق باشید 😁✌️
BY 🧑💻PythonDev🧑💻
Share with your friend now:
tgoop.com/pythonlearnme/255