سطح مقدماتی (Beginner Level)
یکی از مفاهیم پایهای و بسیار مهم در پایتون، درک تفاوت بین اشیاء تغییرپذیر (Mutable) و تغییرناپذیر (Immutable) است. اینکه بدانید کدام دادهها را میتوان تغییر داد و کدامها ثابت هستند، جلوی بسیاری از باگهای ناخواسته را میگیرد.
مفهوم تغییرپذیر (Mutable)
اشیاء Mutable اشیایی هستند که مقدار آنها پس از ساخته شدن قابل تغییر است، بدون اینکه آدرس حافظه (ID) آنها عوض شود. انواع داده رایج Mutable عبارتند از:
- لیستها (Lists)
- دیکشنریها (Dictionaries)
- مجموعهها (Sets)
مثال ۱: تغییر محتوای لیست
در این مثال میبینیم که با تغییر لیست، آدرس حافظه آن ثابت میماند.
مثال ۲: رفتار دیکشنری
دیکشنریها نیز Mutable هستند و میتوان کلیدها و مقادیر آنها را تغییر داد.
مفهوم تغییرناپذیر (Immutable)
اشیاء Immutable اشیایی هستند که پس از ساخته شدن نمیتوانند تغییر کنند. اگر سعی کنید آنها را تغییر دهید، پایتون یک شیء جدید در حافظه میسازد. انواع داده رایج Immutable عبارتند از:
- اعداد (Integers, Floats, Booleans)
- رشتهها (Strings)
- تاپلها (Tuples)
مثال ۳: تلاش برای تغییر رشته
رشتهها تغییرناپذیرند. هر عملیاتی که به نظر میرسد رشته را تغییر میدهد، در واقع یک رشته جدید برمیگرداند.
مثال ۴: تغییر اعداد
حتی اعداد صحیح هم در پایتون Immutable هستند.
# Example 4: Integer reassignment (Static snippet)
x = 10
# با این کار، مقدار ۱۰ تغییر نمیکند، بلکه متغیر x به مکان جدیدی اشاره میکند که مقدار ۱۱ دارد
x = x + 1
سطح پیشرفته (Professional Level)
درک عمیق Mutability برای نوشتن کدهای بهینه و جلوگیری از باگهای پنهان، بهویژه در توابع و مدیریت حافظه، ضروری است.
دام آرگومانهای پیشفرض (Mutable Default Arguments)
یکی از رایجترین اشتباهات حرفهایها، استفاده از یک شیء Mutable (مثل لیست یا دیکشنری) به عنوان مقدار پیشفرض در توابع است. این شیء تنها یک بار در زمان تعریف تابع ساخته میشود و بین تمام فراخوانیها مشترک است.
مثال ۵: باگ لیست مشترک
در اینجا انتظار داریم هر بار یک لیست خالی ایجاد شود، اما لیست قبلی حفظ میشود.
مثال ۶: راه حل صحیح (استفاده از None)
روش استاندارد برای حل مشکل بالا، استفاده از None به عنوان مقدار پیشفرض است.
تاپلهای "تغییرپذیر"! (Immutable containing Mutable)
اگرچه تاپلها Immutable هستند، اما اگر حاوی یک شیء Mutable (مثل لیست) باشند، محتویات آن شیء داخلی قابل تغییر است. این موضوع میتواند در هش کردن (Hashing) و استفاده از تاپل به عنوان کلید دیکشنری مشکل ایجاد کند.
مثال ۷: تغییر محتوای درون تاپل
بهینهسازی حافظه و Interning
پایتون برای اشیاء کوچک Immutable (مثل اعداد صحیح کوچک و رشتههای خاص)، از تکنیکی به نام Interning استفاده میکند تا حافظه را ذخیره کند. یعنی اگر دو متغیر مقدار یکسانی داشته باشند، ممکن است به یک آدرس حافظه اشاره کنند.
مثال ۸: بررسی هویت اشیاء (Is vs Equal)
استفاده در کلیدهای دیکشنری
فقط اشیاء Hashable میتوانند کلید دیکشنری باشند. تمام اشیاء Immutable لزوماً Hashable نیستند (مثل تاپلی که لیست دارد)، اما تمام اشیاء Mutable قطعاً Unhashable هستند.
# Example 9: Valid vs Invalid Dict Keys
valid_dict = {
(1, 2): "Tuple Key", # OK
"key": "String Key", # OK
10: "Int Key" # OK
}
# invalid_dict = {
# [1, 2]: "List Key" # TypeError: unhashable type: 'list'
# }