کپیِ داده همیشه به معنیِ مستقلشدنِ تمامِ محتوا نیست. در Python، انتساب فقط نامِ دیگری را به همان شیء وصل میکند؛ کپیِ سطحی ظرفِ تازه میسازد اما ممکن است عضوِ mutableِ مشترک باقی بماند. در NumPy هم یک برشِ عددی میتواند بافرِ مبدأ را به اشتراک بگذارد. تمرین این صفحه تغییرِ واقعیِ مقدارها را دنبال میکند تا قبل از تبدیلِ دادهٔ مدل بدانیم چه چیزی دستنخورده خواهد ماند.
نامِ تازه، شیء تازه نیست
دادهٔ اصیلِ ما یک dict با weights برابرِ[۲،۴] و tag برابرِ base است. متغیرِ alias را با انتساب از آن میسازیم. مقایسهٔ is نشان میدهد alias و original دقیقاً همان شیء هستند. اگر از نامِ دوم تغییری بدهیم، نسخهٔ پشتیبانِ جدا نداریم؛ فقط راهِ دیگری برای دسترسی به همان وضعیت داریم.
در کنارِ آن، copy.copy و copy.deepcopy را روی همین dictِ ساده اجرا میکنیم. بررسیِ هویت نشان میدهد ظرفِ shallow تازه است، اما shallow['weights'] و original['weights'] همان list هستند. در deep، list نیز برای این دادهٔ محدود جداست. این نتیجه دربارهٔ کلاسِ دلخواه، فایل یا اتصالِ شبکه آزمایش نشده است.
دو تغییر، دو نتیجهٔ متفاوت
از مسیرِ shallow، عضوِ صفرِ weights را۹۹ میکنیم و tag را به shallow تغییر میدهیم. dictِ اصلی حالا weightsِ[۹۹،۴] دارد، ولی tagِ آن همچنان base است. پس هم «همه چیز کپی شد» و هم «هیچ چیز جدا نیست» شرحِ دقیقی از نتیجه نیستند: ظرفِ سطحِ اول جدا و listِ داخلی مشترک بوده است.
| نسخه پس از تغییر | weights | tag |
|---|---|---|
| original و alias | [۹۹،۴] | base |
| shallow | [۹۹،۴] | shallow |
| deep | [۲،۴] | base |
این جدول از اجرای واقعیِ Python۳٫۱۲٫۱۴ آمده است. دادهها ساختگیاند و تابعِ آموزش، کشِ عملیاتی یا تنظیماتِ محصول تغییر نکردهاند. برایِ کنترل، هم مقدارِ نهایی و هم هویتِ عضوهای مهم را میسنجیم؛ صرفاً چاپِ دو dict پیش از تغییر، اشتراکِ پنهان را آشکار نمیکند.
در آرایه، اشتراکِ بافر را بسنجیم
آرایهٔ عددیِ[۱۰،۲۰،۳۰،۴۰] را با dtypeِ int64 میسازیم. سه خروجی داریم: برشِ x[1:3]، انتخابِ پیشرفتهٔ x[[1,2]] و copyِ صریحِ همان برش. در NumPy۲٫۳٫۵، shares_memory برای این سه بهترتیب true، false و false است. این آزمون برای آرایهٔ عددیِ کوچکِ همین مثال است؛ object-dtype را شامل نمیشود.
عضوِ اولِ view را۷۷، عضوِ دومِ advanced را۸۸ و عضوِ اولِ explicit را۶۶ میکنیم. مبدأ فقط به[۱۰،۷۷،۳۰،۴۰] تغییر میکند. view برابرِ[۷۷،۳۰]، advanced برابرِ[۲۰،۸۸] و explicit برابرِ[۶۶،۳۰] میمانند. سه تغییرِ جدا نشان میدهند نتیجهٔ متفاوت فقط از نام یا شکلِ خروجی حدس زده نشده است.
برای مسیرِ اصلاحشده، دو مبدأِ تازهٔ جدا هم داریم. تغییرِ عضوِ کپیِ عمیق به۵۵، dictِ مبدأ را با[۲،۴] نگه میدارد. تغییرِ کپیِ صریحِ برش به[۵۵،۳۰] نیز آرایهٔ مبدأ را دقیقاً[۱۰،۲۰،۳۰،۴۰] حفظ میکند. این دو کنترل، حفظِ اصل را در مسیرِ درست مستقلاً نشان میدهند.
شکلِ درست، استقلال را ثابت نمیکند
راهنمای broadcasting شکل و نگاشتِ اندیس را محاسبه میکند؛ اینجا مسئلهٔ دیگری داریم: نوشتن از یک مسیر، کدام مقدارِ مبدأ را عوض میکند؟ برابرشدنِ شکل یا موفقبودنِ عملیات، مالکیتِ مستقلِ بافر را ثابت نمیکند. reshape نیز بسته به وضعیت میتواند view یا copy بدهد؛ در این تمرین آزمونِ reshape نداریم و آن را همیشه یک نوع نمینامیم.
در استانداردسازی داده، منشأِ میانگین و مقیاس مهم است. حتی اگر منشأ را درست انتخاب کرده باشید، تغییرِ ناخواستهٔ دادهٔ مشترک میتواند نمونهٔ مرجع را عوض کند. جداکردنِ مرجعِ تبدیل و جداکردنِ حافظه دو کنترلاند؛ موفقیتِ یکی بهتنهایی شاهدِ دیگری نیست.
چه چیزی را برای پروژه ثبت کنیم؟
پیش از تغییرِ in-place، مشخص کنید مبدأ باید حفظ شود یا تغییرِ مشترک عمدی است. برای چند عضوِ حساس، مقدارِ قبل/بعد و رابطهٔ اشتراک را در آزمونِ کوچک نگه دارید. deepcopy راهحلِ عمومیِ امنیت یا راهِ کپیِ هر شیء نیست؛ رفتارِ کلاسهای سفارشی و هزینهٔ دادهٔ بزرگ به بررسیِ جدا نیاز دارد. این مثال نه سرعت را اندازه گرفته و نه مصرفِ حافظهٔ مدل را.
برای ادامهٔ مبانی به صفحهٔ هوش مصنوعی بروید. اگر مسئله، آمادهسازیِ دادهٔ اتصالِ پاسخگویی است، ورودیِ مرجع و تغییرهای مجاز را در مسیر راهکارهای اپرا مشخص کنید؛ این تمرین روشِ داخلیِ ذخیرهسازی یا کپی در محصولات اپرا را اعلام نمیکند.
فایل تمرین و منبع
کد مستقلِ تمرینِ محدود · تمام خروجیِ واقعیِ همین تمرین؛ JSON
- Python۳٫۱۲؛ انتساب و کپی سطحی/عمیقِ ظرف و محدودیتِ اشیای سفارشی
- NumPy۲٫۳؛ بافر، برشِ پایه، انتخابِ پیشرفته و مرز reshape
منابع در 2026-11-04 خوانده شدند؛ این تاریخ، تاریخ انتشار منبع نیست. مثالها و فایلهای این راهنما آموزشی و ساختهٔ تحریریهاند.