سلام، امیدوارم که مثل همیشه خوش و خرم باشید. درمجموعه پایتونیک هدفمون این بود که راجعبه چیزهایی صحبت کنیم که باعث میشن یک قدم خوانایی کدمون بالاتر بره. در این قسمت از پایتونیک سراغِ یک مبحث خیلی پایهای رفتیم که در عین سادگیِ میتونه باعث افزایشِ خوانایی کدمون بشه. چند وقت پیش مطلبی جالبی رو خوندم که تو دلِ اون مطلب یکم راجعبه برابری و هویت متغییرها در پایتون بحث شده بود. دوست داشتم اون مطلب رو با شما هم به اشتراک بذارم.
انتظار داریم در انتهای این قسمت به این نتیجه برسیم که درستترین حالتِ استفاده از عملگر == و is به چه صورت هست و این اصل رو به صورت روزمره بکار ببریم.
توی پایتون وقتی میخواهیم ببینم دو آبجکت با هم برابر هستند یا خیر، از عملگرهای == و =! استفاده میکنیم.
در مقابل این عملگرها، دوتا عملگر دیگه هم داریم که is و is not هستند. is بررسی میکنه که آیا این آبجکت دقیقا یک آبجکت هستند یا نه. دقت کنید، ما داریم راجعبه چیزی فراتر از برابری حرف میزنیم. وقتی میگیم یکی هستند یا نه به صورت خیلی تخصصی یعنی اون دو متغییر دقیقاً در یک مکان از حافظه قرار گرفتند (ارجاعی به یک خونه از حافظه هستند)، یعنی این دو متغییر صرفا دو تا اسم هستند که دارند به یک جا اشاره میکنند.
بریم با یک مثال مطلب رو بهتر جا بندازیم. توی قطعه کد پایین، با استفاده از تابع سازنده لیست، دو لیست مجزا (و خالی) رو در دو متغییر x و y ذخیره کردیم. دو متغییر x و z دقیقا به ایک آبجکت اشاره میکنند.
چطور میتونیم بفهمیم دقیقاً به یک آبجکت اشاره میکنند؟ کافیه چک کنیم که هر متغییر دقیقاً به چه آدرسی از حافظه داره اشاره میکنه:
و اگر از عملگر is بپرسیم که کدوم دو متغییر هویت یکسانی دارند:
با توضیحات بالا شما باید الان یک همچین تصوری از این سه متغییر داشته باشید:
همونطور که گفتیم، محتوای هر سه متغییرها یک لیست خالی هست، در نتیجه بدیهی که انتظار داشته باشیم خروجی عملگر == برای سه متغییر یکی باشه:
نکته دوم، این هست که هر آبجکتی میتونه نحوه بررسی == رو خودش پیادهسازی کنه. این کار توسط تابع __eq__ (بخونید داندِر equal) انجام میشه. مثلاً میتونیم آبجکتی بسازیم که با هر چیزی مقایسه بشه، همیشه True برگردونه.
وقتی ابجکتهایی که در حال مقایسه هستند یکی از حالتهای زیر باشند، به جای عملگر == باید از عملگر is استفاده کرد:
چرا؟؟؟!
چون این آبجکتها به صورت پیشفرض توی پایتون به صورت singleton پیادهسازی شدهاند. یعنی مهم نیست چند تا از اینها داشته باشیم. همهی اونها به یک آدرس از حافظه اشاره میکند.
خیلی از چیزهای دیگه با هم برابر هستند اما به هیچعنوان به یک آدرس از حافظه اشاره نمیکنند. پس فقط برای سه حالت بالا از عملگر is استفاده کنید.
به طور کلی میشه گفت هر موقع به دنبال بررسی یکی بودن محتوای دو آبجکت هستیم، عملگری که باید استفاده بشه == هست. در مقابل، هر موقع انتظار میره که دو آبجکت هویتِ یکسان داشته باشند (به یک آدرس از حافظه اشاره کنند، یا دقیقا یکی هستند دو متغییر که صرفا به یک آدرس از حافظه اشاره میکنند) از عملگر is باید استفاده بشه.
x is something_unique_object
بهترین کار درست کردن کدهای قدیمی هست. هر کجا چیزی شبیه کدهای پایین دارید رو به حالت درستش بازنویسی کنید:
اگر مطلب به صورت کامل برای شما جا نیفتاده میتونید لینکهای پایین رو بررسی کنید: