سطح مقدماتی (Beginner Level)
در پایتون، مدیریت متغیرها و نحوه ذخیرهسازی آنها در حافظه با بسیاری از زبانهای دیگر متفاوت است. یکی از رایجترین اشتباهات برنامهنویسان، تصور این است که علامت مساوی (=) همیشه یک کپی جدید از داده ایجاد میکند. در این بخش یاد میگیریم که چگونه از دادههای خود به درستی کپی بگیریم.
۱. انتساب در برابر کپی (Assignment vs Copy)
وقتی یک لیست یا دیکشنری را با علامت = به متغیر دیگری اختصاص میدهید، شما داده را کپی نمیکنید؛ بلکه فقط یک برچسب (Reference) جدید به همان مکان در حافظه میزنید. تغییر در یکی، باعث تغییر در دیگری میشود.
مثال ۱: رفتار پیشفرض انتساب (بدون کپی)
مثال ۲: بررسی شناسه حافظه (id)
با استفاده از تابع id() میتوانیم ببینیم که هر دو متغیر دقیقاً یک شیء هستند.
۲. کپی سطحی (Shallow Copy)
برای اینکه تغییرات روی متغیر جدید، متغیر اصلی را خراب نکند، باید از کپی استفاده کنیم. سادهترین روش، کپی سطحی است. در لیستها میتوانیم از متد .copy() یا اسلایسینگ [:] استفاده کنیم.
مثال ۱: استفاده از متد copy
مثال ۲: استفاده از Slicing (روش پایتونی)
مثال ۳: کپی در دیکشنریها
# Example 3: Static snippet for dict (works same as list)
data = {"name": "Ali", "age": 25}
data_copy = data.copy()
سطح پیشرفته (Professional Level)
زمانی که با اشیاء تو در تو (Nested Objects) کار میکنیم (مثلاً لیستی که داخلش لیست دیگری دارد)، کپی سطحی دیگر امن نیست. در اینجا باید تفاوت دقیق نحوه مدیریت حافظه در Shallow Copy و Deep Copy را درک کنیم.
۱. مشکل کپی سطحی در دادههای تو در تو
کپی سطحی فقط لایه اول (کانتینر اصلی) را کپی میکند، اما ارجاعهای داخلی (اشیاء فرزند) را کپی نمیکند. یعنی اگر لیست داخلی را تغییر دهید، در هر دو متغیر تغییر میکند.

مثال ۱: شکست کپی سطحی
۲. کپی عمیق (Deep Copy)
برای حل این مشکل، ماژول استاندارد copy و تابع deepcopy را داریم. این تابع به صورت بازگشتی تمام اشیاء داخلی را پیدا کرده و کپی میکند.
مثال ۱: استفاده از copy.deepcopy
مثال ۲: مقایسه عملکرد روی دیکشنریهای تو در تو
۳. نکات فنی و پرفورمنس
- هزینه:
deepcopyبسیار کندتر ازcopyسطحی است زیرا باید کل درخت اشیاء را پیمایش کند. اگر دادههای تو در تو ندارید، هرگز ازdeepcopyاستفاده نکنید. - اشیاء تغییرناپذیر (Immutable): کپی کردن (چه سطحی چه عمیق) روی اشیاء تغییرناپذیر مثل Tuple یا String معمولاً کپی جدید ایجاد نمیکند و پایتون برای بهینهسازی همان ارجاع قبلی را برمیگرداند.
مثال: بهینهسازی در تاپلها
۴. شخصیسازی کپی با Magic Methods
شما میتوانید نحوه کپی شدن کلاسهای خود را با متدهای __copy__ و __deepcopy__ کنترل کنید.
# Static Example: Customizing copy behavior
import copy
class MyData:
def __init__(self, data):
self.data = data
def __copy__(self):
# منطق دلخواه برای کپی سطحی
print("Custom shallow copy triggered")
return MyData(self.data)
def __deepcopy__(self, memo):
# منطق دلخواه برای کپی عمیق
print("Custom deep copy triggered")
return MyData(copy.deepcopy(self.data, memo))