آموزش پایتون - هویت اشیاء

در این سری از مقالات قصد دارم نکات کلیدی که در زبان پایتون وجود دارد را ارائه کنم. در این مجموعه تلاش شده اطلاعات مختصر و کوتاه باشند و بر مهمترین نکات مورد نیاز تمرکز شود. 

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

عناوین دوره:

  1. مقدمه
  2. نصب و راه‌اندازی
  3. متغیرها و انواع داده
  4. عبارت‌های کنترلی
  5. توابع و ماژول‌ها
  6. هویت اشیاء
  7. مدیریت خطا
  8. برنامه‌نویسی شی‌گرا
  9. بسته‌بندی و انتشار کد

در این مقاله یکی از مهم‌ترین مفاهیم در پایتون بنام هویت اشیاء (Object Identity) را توضیح می‌دهیم. همانطور که در بخش متغیرها و انواع داده‌ها نیز اشاره شد هر چیزی در پایتون یک شی محسوب می‌شود. 

هر زمان که ما یک شی را در پایتون به صورت یک متغیر، تابع، و غیره ایجاد می‌کنیم، مفسر پایتون (CPython) یک آدرس در حافظه اختصاص می‌دهد که به صورت منحصر به فرد آن شی را مشخص می‌کند. تابع id در پایتون کد شناسایی مربوط به آدرس اختصاصی هر شی را برمی‌گرداند.

 

اجازه دهید با یک مثال مفهوم را بصورت جزئی‌تر توضیح دهیم:

Image for post
Image for post

همانطور که مشاهده می‌کنید به هر متغیر یک مقدار عدد صحیح به عنوان کد شناسایی آدرس آن متغیر در حافظه نسبت داده شده است.

حال تصور کنید دو متغیر ایجاد کنیم و به آن‌ها متغیرهایی که قبلا بوجود آورده‌ایم را اختصاص دهیم:

Image for post
Image for post

همانطور که ملاحظه می‌کنید پایتون آدرس جدیدی در حافظه برای متغیرهای 5 و 6 بوجود نمی‌آورد و آن‌ها را با همان متغیرهای 1 و 4 آدرس‌دهی می‌کند.

 

حال فرض کنید بخواهیم یک متغیر را مجددا مقدار دهی کنیم:

Image for post
Image for post

این یعنی زمانیکه بخواهیم یک متغیر را مجددا مقدار ‌دهی کنیم یک آدرس جدید برای ذخیره متغیر ایجاد خواهد شد. حال بیاید یک مورد به متغیر 6 که با متغیر 4 آدرس یکسانی در حافظه دارد، اضافه کنیم:

Image for post
Image for post

عجیب نیست؟؟؟ کد شناسایی یکسان حتی پس از تغییر!! 

 

دقت کنید همانطور که در بخش داده‌ها نیز به آن اشاره شد برخی از داده‌ها در پایتون تغییرپذیر (Mutable) و برخی دیگر تغییرناپذیرند (Immutable).

Image for post
Image for post

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

 

اجازه دهید تا با یک تابع کمی بیشتر در مورد متغیر و آدرس دهی حافظه آن توسط CPython صحبت کنیم. در مثال زیر ما یک متغیر از نوع تغییرپذیر را مقداردهی می‌کنیم سپس متغیر به تابع وارد شده و درون تابع بروزرسانی می‌شود.

Image for post
Image for post

همانطور که مشاهده می‌کنید متغیر درون تابع به همان آدرس متغیر 6 اشاره دارد. این نشان می‌دهد که تابع همان شی را بروز کرده است. 

 

در مثال زیر متغیر 6 درون تابع مجددا مقدار دهی می‌شود:

Image for post
Image for post

این نشان می‌دهد که متغیر به محض مقداردهی درون تابع از شناسه متفاوتی برخوردار می‌شود و بدون توجه به نوع داده (تغییرپذیر یا تغییرناپذیر) با خروج از محل تابع، دیگر به آن دسترسی نداریم.

پایتون همیشه یک آدرس حافظه جدید برای همه متغیرهای جدید ایجاد نمی‌کند. بصورت مشخص‌تر متغیرهای تغییرپذیر list, set و dictionary در پایتون با بروزرسانی حتی درون یک تابع نیز آدرس جدیدی در حافظه ایجاد نمی‌کنند.

 

حال حدس می‌زنید اگر ما به دو متغیر متفاوت یک مقدار یکسان مانند "a" نسبت دهیم، آیا دو آدرس حافظه برای شما ایجاد خواهد کرد؟

Image for post
Image for post

همانطور که مشاهده می‌کنید هر دو متغیر آدرس یکسانی در حافظه دارند.

حال اگر به دو متغیر یک رشته طولانی نسبت دهیم چه اتفاقی خواهد افتاد؟

Image for post
Image for post

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


در این مقاله در مورد مفهوم هویت اشیاء در پایتون صحبت در مقاله بعد در مورد مدیریت خطا صحبت خواهیم کرد.