بی آکادمی
آموزش HTML
آموزش CSS
فلکس باکس
جاوااسکریپت
آموزش SQL
آموزش MySQL
آموزش PHP
آموزش لاراول
دانلود و نصب لینوکس
داکر دسکتاپ
VS Code
گیت و گیت هاب
آموزش پایتون
هوش مصنوعی
TypeScript
فروشگاه اینترنتی
اپلیکیشن موبایل
آموزش اکسل

آموزش جامع عملگرهای هویت در پایتون


🎯 اهداف یادگیری

  • درک مفهوم هویت (Identity) در پایتون
  • شناخت عملگرهای is و is not
  • یادگیری تفاوت اساسی بین "هویت" و "برابری مقدار"
  • آشنایی با تابع id() و مفهوم آدرس حافظه
  • کاربرد صحیح عملگر is در مقایسه با None
  • درک بهینه‌سازی CPython (Interning) برای اعداد و رشته‌ها

📌 مقدمه‌ای بر عملگرهای هویت

عملگرهای هویت در پایتون برای بررسی یکسان بودن دو شیء (اشاره‌گر به یک مکان یکسان در حافظه) استفاده می‌شوند، نه صرفاً یکسان بودن مقادیر آنها. این عملگرها پایه درک مدل داده شیءگرا در پایتون هستند.


📌 عملگرهای is و is not

پایتون دو عملگر هویت ارائه می‌دهد:

python
# عملگر is (بررسی هویت یکسان)
x = [1, 2, 3]
y = x # y به همان شیء x اشاره می‌کند
print(x is y) # خروجی: True
# عملگر is not (بررسی هویت ناهمسان)
z = [1, 2, 3] # ایجاد یک شیء جدید با مقدار مشابه
print(x is not z) # خروجی: True

جدول عملگرهای هویت:

عملگر توضیح مثال نتیجه
is بررسی یکسان بودن هویت دو شیء x is y True اگر هر دو به یک شیء اشاره کنند
is not بررسی ناهمسان بودن هویت دو شیء x is not y True اگر به دو شیء مختلف اشاره کنند

📌 تابع id() و مفهوم هویت

هر شیء در پایتون یک هویت منحصر به فرد دارد که با تابع id() قابل دسترسی است. این تابع یک عدد صحیح برمی‌گرداند که نمایانگر آدرس حافظه شیء است.

python
a = 500
b = a
c = 500
print(id(a)) # آدرس حافظه شیء a
print(id(b)) # همان آدرس a (اشاره به یک شیء)
print(id(c)) # آدرس متفاوت (شیء جدید با مقدار مشابه)
# عملگر is معادل مقایسه idهاست
print(a is b) # True
print(id(a) == id(b)) # True
print(a is c) # False
print(id(a) == id(c)) # False

📌 تفاوت اساسی is و ==

این تفاوت یکی از مهم‌ترین مفاهیم در پایتون است که بسیاری از برنامه‌نویسان مبتدی در آن دچار اشتباه می‌شوند:

python
# ایجاد دو لیست با مقادیر یکسان
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1 # اشاره‌گر به همان شیء list1
# مقایسه مقدار (برابری)
print(list1 == list2) # True - مقادیر یکسان هستند
print(list1 == list3) # True - مقادیر یکسان هستند
# مقایسه هویت (یکسانی شیء)
print(list1 is list2) # False - دو شیء مختلف در حافظه
print(list1 is list3) # True - یک شیء یکسان در حافظه
# تغییر list1 بر list3 تأثیر می‌گذارد اما بر list2 نه
list1.append(4)
print(list1) # [1, 2, 3, 4]
print(list2) # [1, 2, 3] (تغییر نکرده)
print(list3) # [1, 2, 3, 4] (تغییر کرده)

تفاوت‌های کلیدی is و ==:

عملگر هدف مقایسه سرعت کاربرد اصلی
== برابری مقدار مقادیر درون شیءها کندتر (نیاز به مقایسه محتوا) مقایسه داده‌ها و محتوا
is یکسانی هویت آدرس حافظه شیءها سریع‌تر (مقایسه اشاره‌گر) بررسی Singletonها مثل None

📌 بهینه‌سازی CPython (Interning)

مفسر CPython برای صرفه‌جویی در حافظه، برخی از انواع داده را "internal" می‌کند. این به این معنی است که برای مقادیر خاص، تنها یک نسخه در حافظه ذخیره می‌شود:

python
# Interning اعداد کوچک (۵- تا ۲۵۶)
a = 100
b = 100
print(a is b) # True - بهینه‌سازی CPython
c = 500
d = 500
print(c is d) # False - خارج از محدوده بهینه‌سازی
# Interning رشته‌های کوتاه
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True - بهینه‌سازی رشته‌های کوتاه
s3 = "this is a long string that may not be interned"
s4 = "this is a long string that may not be interned"
print(s3 is s4) # False (در برخی پیاده‌سازی‌ها)

نکات مهم درباره Interning:

  • اعداد کوچک: اعداد از ۵- تا ۲۵۶ همیشه interned هستند
  • رشته‌های کوتاه: رشته‌هایی که فقط شامل حروف، اعداد یا underline باشند ممکن است interned شوند
  • تغییرپذیر بودن: فقط اشیاء تغییرناپذیر (immutable) می‌توانند interned شوند
  • وابسته به پیاده‌سازی: این رفتار در CPython تضمین شده نیست و ممکن است تغییر کند

📌 کاربرد صحیح is و is not با None

همیشه برای مقایسه با مقدار None از عملگر is استفاده کنید:

python
# روش صحیح: استفاده از is برای مقایسه با None
value = None
if value is None:
print("مقدار None است")
if value is not None:
print("مقدار None نیست")
# روش نادرست: استفاده از == برای مقایسه با None
if value == 极None: # این روش توصیه نمی‌شود
print("این روش ممکن است مشکلاتی ایجاد کند")
# دلیل: برخی کلاس‌ها ممکن است متد __eq__ را بازنویسی کنند
class CustomClass:
def __eq__(self, other):
return True # همیشه True برمی‌گرداند!
obj = CustomClass()
print(obj == None) # True (نادرست!)
print(obj is None) # False (صحیح)

📌 خلاصه و بهترین practices

چه زمانی از is استفاده کنیم:

  • مقایسه با None: همیشه از is یا is not استفاده کنید
  • بررسی Singletonها: برای مقایسه با مقادیر ثابت مانند True، False (البته معمولاً == ترجیح داده می‌شود)
  • بهینه‌سازی عملکرد: زمانی که مطمئن هستید با یک شیء خاص کار می‌کنید

چه زمانی از == استفاده کنیم:

  • مقایسه مقادیر: هنگامی که می‌خواهید بدانید محتوای دو شیء یکسان است
  • اکثر موارد استفاده: بیش از ۹۵٪ موارد مقایسه باید با == انجام شود
  • برابری منطقی: وقتی نگران هویت شیء نیستید، فقط برابری مقدار مهم است

نکات نهایی:

  • هرگز برای مقادیر عددی یا رشته‌ای از is استفاده نکنید (مگر اینکه دقیقاً بدانید چه می‌کنید)
  • به خاطر داشته باشید که بهینه‌سازی interning در پایتون ممکن است تغییر کند
  • همیشه برای خوانایی و قابلیت نگهداری کد، از == استفاده کنید مگر اینکه دلیل محکمی برای استفاده از is داشته باشید

📌 تمرین‌های عملی

حالا نوبت شماست! کدهای زیر را بررسی کنید و نتیجه را پیش‌بینی کنید:

python
# تمرین ۱
a = 256
b = 256
print(a is b)
# تمرین ۲
x = 257
y = 257
print(x is y)
# تمرین ۳
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2)
print(list1 is list2)
# تمرین ۴
text = "hello"
print(text is "hello")