فرض کنید در حال نوشتن یک برنامه با پایتون هستید و می‌خواهید بررسی کنید آیا دو متغیر مقدار یکسانی دارند یا خیر. برای انجام این کار، از یک شرط ساده استفاده می‌کنید و انتظار دارید برنامه در صورت برابر بودن مقادیر، وارد بخش مشخصی از کد شود. اما برخلاف انتظارتان، شرط اجرا نمی‌شود و برنامه نتیجه اشتباهی به شما می‌دهد.

اولین چیزی که احتمالاً به ذهن شما می‌رسد، وجود یک مشکل پیچیده در منطق برنامه است؛ درحالی‌که ممکن است دلیل این اتفاق فقط استفاده از یک عملگر اشتباه باشد! یکی از اشتباهاتی که به‌خصوص برنامه‌نویسان تازه‌کار پایتون مرتکب می‌شوند، استفاده از عملگر is به‌جای == است. این دو عملگر در ظاهر کاربرد مشابهی دارند، اما وظیفه آن‌ها کاملاً متفاوت است. اگر تفاوت این دو را به‌درستی نشناسید، ممکن است در شرایط مختلف با رفتارهای غیرمنتظره‌ای در برنامه خود روبه‌رو شوید.

در ادامه با یک مثال ساده شروع می‌کنیم و سپس بررسی می‌کنیم این اشتباه دقیقاً چگونه اتفاق می‌افتد و چه زمانی باید از هرکدام از این عملگرها استفاده کنید. با استاد پلاس همراه باشید.


تفاوت عملگرهای == و is در پایتون چیست؟

برای درک این اشتباه، ابتدا باید بدانید که پایتون بین برابر بودن مقدار دو متغیر و یکسان بودن خود آن‌ها تفاوت قائل می‌شود. عملگر == برای مقایسه مقدار دو شیء استفاده می‌شود یعنی بررسی می‌کند آیا اطلاعاتی که در دو متغیر قرار دارند با یکدیگر برابر هستند یا خیر و در مقابل، عملگر is بررسی می‌کند که آیا دو متغیر دقیقاً به یک شیء واحد در حافظه اشاره می‌کنند یا خیر.

برای اینکه تفاوت این دو موضوع را بهتر متوجه شوید، مثال زیر را در نظر بگیرید:

a = [10, 20, 30]

b = [10, 20, 30]

print(a == b)

print(a is b)

خروجی برنامه:

True

False

شاید در نگاه اول این نتیجه کمی عجیب به نظر برسد. هر دو متغیر دقیقاً شامل اعداد یکسانی هستند، پس چرا نتیجه دستور دوم False شده است؟ دلیل این موضوع به نحوه ایجاد اشیا در پایتون برمی‌گردد. در این مثال، ما دو لیست جداگانه ایجاد کرده‌ایم. هرچند محتوای آن‌ها کاملاً یکسان است، اما هر لیست یک شیء مستقل محسوب می‌شود.

بنابراین، وقتی از == استفاده می‌کنیم، پایتون محتوای دو لیست را با یکدیگر مقایسه می‌کند و به دلیل یکسان بودن مقادیر، نتیجه True خواهد بود. اما هنگام استفاده از is، پایتون بررسی می‌کند که آیا هر دو متغیر به همان لیست واحد اشاره دارند یا خیر؛ در این مثال پاسخ منفی است.

حالا اگر متغیر دوم را به متغیر اول نسبت دهیم، نتیجه تغییر می‌کند:

a = [10, 20, 30]

b = a

print(a == b)

print(a is b)

خروجی:

True

True

این بار هر دو نتیجه True هستند؛ زیرا متغیر b یک لیست جدید نساخته است، بلکه به همان شیئی اشاره می‌کند که در متغیر a قرار دارد.

آیا کد پایتون شما نتایج اشتباه تولید می‌کند؟ این اشتباه رایج را بررسی کنید!


یک اشتباه رایج در شرط‌های برنامه‌نویسی

حالا فرض کنید می‌خواهید در یک برنامه بررسی کنید آیا نام کاربری واردشده توسط کاربر با یک مقدار مشخص برابر است یا خیر.

ممکن است کدی شبیه نمونه زیر بنویسید:

username = input("Enter username: ")

if username is "admin":

    print("Welcome Admin")

else:

    print("Access Denied")

هدف ما این است که اگر کاربر عبارت admin را وارد کرد، پیام خوشامدگویی نمایش داده شود. اما استفاده از is برای این مقایسه اشتباه است؛ زیرا ما قصد نداریم بررسی کنیم متغیر username و رشته "admin" یک شیء واحد هستند. چیزی که اهمیت دارد، برابر بودن محتوای آن‌هاست.

بنابراین، شکل صحیح کد به این صورت خواهد بود:

username = input("Enter username: ")

if username == "admin":

    print("Welcome Admin")

else:

    print("Access Denied")

با این تغییر، پایتون مقدار واردشده توسط کاربر را با رشته admin مقایسه می‌کند و در صورت برابر بودن آن‌ها، شرط اجرا می‌شود.

نکته مهم این است که ممکن است در بعضی شرایط، استفاده اشتباه از is ظاهراً نتیجه درستی به شما بدهد. این اتفاق به دلیل برخی بهینه‌سازی‌های داخلی پایتون و نحوه نگهداری بعضی اشیا رخ می‌دهد. اما نباید به چنین رفتاری تکیه کنید؛ زیرا ممکن است با تغییر شرایط یا نسخه محیط اجرا، نتیجه متفاوتی دریافت کنید.


پس چه زمانی باید از is استفاده کنیم؟

تا اینجا متوجه شدیم که برای مقایسه مقدار متغیرها و بررسی برابر بودن اطلاعات داخل آن‌ها باید از عملگر == استفاده کنیم؛ اما این موضوع به معنای بی‌استفاده بودن عملگر is نیست. در واقع، این عملگر کاربرد مهمی در پایتون دارد و زمانی استفاده می‌شود که بخواهیم مطمئن شویم دو متغیر دقیقاً به یک شیء واحد در حافظه اشاره می‌کنند، نه اینکه فقط مقادیر یکسانی داشته باشند. یکی از رایج‌ترین و مهم‌ترین موارد استفاده از is، بررسی مقدار None است.

در پایتون، None یک مقدار ویژه و از نوع داده‌ای NoneType است که معمولاً برای نشان دادن نبودن یک مقدار، مشخص نبودن نتیجه یا خالی بودن یک متغیر از نظر منطقی استفاده می‌شود. برای مثال، تصور کنید تابعی نوشته‌اید که وظیفه آن جست‌وجوی یک کاربر در میان اطلاعات ذخیره‌شده است. اگر کاربر موردنظر در سیستم وجود داشته باشد، تابع اطلاعات او را برمی‌گرداند؛ اما اگر چنین کاربری پیدا نشود، ممکن است تابع مقدار None را برگرداند. در این شرایط، برنامه باید بتواند تشخیص دهد که آیا نتیجه‌ای دریافت کرده است یا خیر.

برای بررسی چنین وضعیتی، بهتر است از عملگر is استفاده کنید. به مثال زیر توجه کنید:

result = None if result is None:    print(“No result found”)else:    print(result)

در این مثال، ابتدا متغیر result را با مقدار None مقداردهی کرده‌ایم و سپس با استفاده از شرط if بررسی می‌کنیم که آیا مقدار این متغیر واقعاً None است یا خیر. اگر شرط برقرار باشد، پیام No result found نمایش داده می‌شود؛ در غیر این صورت، مقدار موجود در متغیر چاپ خواهد شد.

دلیل اینکه در این شرایط از is None استفاده می‌کنیم، این است که قصد داریم هویت شیء را بررسی کنیم و مطمئن شویم مقدار متغیر دقیقاً همان شیء ویژه None است. از آنجا که None در پایتون یک شیء یکتا محسوب می‌شود، استفاده از is روش استاندارد و مطمئنی برای انجام این بررسی است. هرچند ممکن است استفاده از == None نیز در بسیاری از موارد نتیجه موردانتظار را برگرداند، اما روش توصیه‌شده در پایتون استفاده از is None است؛ زیرا مقایسه هویتی انجام می‌دهد و از رفتارهای احتمالی و غیرمنتظره عملگرهای مقایسه سفارشی جلوگیری می‌کند.

همچنین اگر بخواهید بررسی کنید که یک متغیر مقدار None ندارد، می‌توانید از عملگر is not استفاده کنید. این عملگر دقیقاً برعکس is عمل می‌کند و زمانی نتیجه True می‌دهد که متغیر به شیء موردنظر اشاره نکند. برای مثال:

result = “Python Programming” if result is not None:    print(“Result is available”)

در این کد، ابتدا بررسی می‌شود که آیا متغیر result مقداری غیر از None دارد یا خیر. از آنجا که در این مثال یک رشته در متغیر قرار گرفته است، شرط برقرار می‌شود و پیام Result is available نمایش داده خواهد شد.

بنابراین، بهتر است هنگام برنامه‌نویسی این تفاوت را به خاطر داشته باشید: زمانی که هدف شما مقایسه محتوای دو متغیر است، از == استفاده کنید؛ اما زمانی که می‌خواهید هویت یک شیء را بررسی کنید یا مطمئن شوید یک متغیر مقدار None دارد، عملگر is انتخاب مناسب‌تری است. رعایت همین نکته ساده می‌تواند از بروز برخی خطاهای منطقی در برنامه جلوگیری کند و باعث شود کدهای شما مطابق استانداردهای رایج پایتون نوشته شوند.

آیا کد پایتون شما نتایج اشتباه تولید می‌کند؟ این اشتباه رایج را بررسی کنید!


چگونه از تکرار این اشتباه در پروژه‌های پایتون جلوگیری کنیم؟

برای جلوگیری از این خطا، لازم نیست کار پیچیده‌ای انجام دهید. کافی است هنگام نوشتن شرط‌ها به هدف مقایسه خود توجه کنید. اگر می‌خواهید بدانید دو متغیر مقدار یکسانی دارند، از == استفاده کنید. اما اگر قصد دارید بررسی کنید دو متغیر به یک شیء واحد اشاره می‌کنند، is انتخاب مناسبی خواهد بود.

بهتر است این تفاوت را در کدنویسی روزمره خود به خاطر بسپارید:

  • مقایسه رشته‌ها، اعداد و محتوای لیست‌ها: استفاده از ==
  • بررسی یکسان بودن هویت دو شیء: استفاده از is
  • بررسی خالی بودن یا نبودن یک مقدار از نوع None: استفاده از is None یا is not None

اگر هنگام اجرای برنامه با شرطی روبه‌رو شدید که برخلاف انتظار شما عمل می‌کند، بررسی عملگرهای مقایسه یکی از اولین کارهایی است که باید انجام دهید.


جمع‌بندی:

یکی از مهم‌ترین مهارت‌هایی که یک برنامه‌نویس پایتون باید به دست بیاورد، شناخت دقیق رفتار عملگرها و ابزارهای زبان برنامه‌نویسی است. عملگرهای == و is ممکن است در نگاه اول کاربرد مشابهی داشته باشند، اما تفاوت آن‌ها در نحوه مقایسه اشیا اهمیت زیادی دارد. استفاده از == برای مقایسه مقادیر و استفاده از is برای بررسی هویت اشیا، از بروز بسیاری از خطاهای منطقی جلوگیری می‌کند. همچنین به خاطر داشته باشید که برای بررسی None بهتر است همیشه از is None استفاده کنید.

اگر می‌خواهید کدهای پایتون شما قابل‌اعتمادتر باشند، تنها به درست اجرا شدن برنامه اکتفا نکنید؛ سعی کنید دلیل رفتار هر دستور را نیز به‌خوبی درک کنید.