✅ مطلبی در مورد تفاوت == و is از کانال @osmanpydev
ما وقتی ی متغیر میسازیم، مثلا ی لیست، به این صورت:
list1 = [1, 2, 3, 4]
این متغیری که لیستمون رو بهش نسبت دادیم به ی خونه از حافظه رم اشاره میکنه، یعنی این لیست رو داخل ی خونه رم میذاره و به آدرس اون خونه اشاره میکنه.
حالا ی لیست دیگه بسازیم:
list2 = list1
در واقع ما گفتیم لیست دوم هم به همون آدرسی که لیست یک اشاره میکرد اشاره کنه.
حالا هر تغییری تو لیست یک یا لیست دو ایجاد کنیم اون یکی هم تغییر میکنه، مثلا:
list2.append(5)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
ولی اگه بیایم بگیم:
list3 = list1[:]
اینجا میگیم ی لیست بساز و آیتمهای لیست یک رو بریز داخلش، ولی نگفتیم لیست سه = لیست یک؛ بنابراین لیست سه به ی خونه دیگه از حافظه رم اشاره میکنه ولی مقدارش همون مقدار لیست یک هست.
به این ترتیب اگه بگیم:
list3.append(6)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
print(list3) -> [1, 2, 3, 4, 5, 6]
چون ما دیتای ی خونه دیگه از حافظه رم رو تغییر دادیم و فقط مقدار متغیری که به اون خونه اشاره میکنه تغییر کرد.
برای متوجه شدن این تفاوت میتونید با دستور زیر نتیجه رو ببینید:
print(id(list1))
print(id(list2))
print(id(list3))
تابع id آدرس خونهای که متغیر بهش اشاره میکنه رو میده، اینجا لیست یک و لیست دو ی چیز رو چاپ میکنن ولی لیست سه ی چیز دیگه رو چاپ میکنه.
حالا علامت == فقط مقدار دو تا متغیر رو با هم مقایسه میکنه ولی علامت is میاد هم مقدارشون و هم اینکه به ی خونه اشاره میکنن یا نه رو بررسی میکنه، پس:
list1 is list2 -> True
list1 == list2 -> True
list1 is list3 -> False
list1 == list3 -> False (البته چون اونجا ۶ رو به لیست سه اضافه کردیم)
قبل append
list1 == list3 -> True
این همون مفهوم (کپی سطحی)shallow copy در پایتونه.
روش اول کپی نکرد، بلکه آدرس خونه رم رو به متغیر دوم نسبت داد ولی دومی کپی سطحی کرد.
حالا فرض کنید لیست اول رو به این صورت تعریف کردیم:
list1 = [1, 2, [3, 4], 5]
یعنی ی لیست دیگه هم بعنوان ی آیتم بهش دادیم، یعنی بعبارتی لیست تو در تو ایجاد کردیم.
اینجا اگه از روش کپی سطحی استفاده کنیم بازم همون مشکل اول بوجود میاد؛ چون باز آدرس خونه رم لیست داخلی رو داد به متغیر دومی.
list2 = list1[:]
حالا فرض کنید تغییر رو بصورت زیر اعمال کردیم:
list2[2][0] = 9
دوباره خروجی لیست اول رو ببینید:
print(list1) -> [1, 2, [9, 4], 5]
چطور میتونیم جلوی این مشکل رو بگیریم و بعبارتی ی (کپی عمیق)deepcopy داشته باشیم؟
با استفاده از کتابخونه داخلی copy:
import copy
list2 = copy.deepcopy(list1)
البته میشه با همین کتابخونه هم ی کپی سطحی داشت، بصورت زیر:
list3 = copy.copy(list1)
سعی میکنم بیشتر درموردش صحبت کنم.