NumPy: النسخ والعروض

آخر تحديث: 2026-08-26

عدّل تشارلي مصفوفة فرعية واكتشف أن المصفوفة الأصلية تغيرت أيضاً — أمضى ساعتين في التصحيح. تقول أليس: "تحقق من الخاصية .base. إذا كان base is هو المصفوفة الأصلية، فهو عرض. عندما تشك، استخدم .copy()."

تسلط هذه القصة الضوء على مشكلة جوهرية: ليست كل عمليات NumPy تُرجع مصفوفات مستقلة. فهم الفرق بين العروض والنسخ أمر أساسي لتجنب أخطاء تعديل البيانات الخفية.


1. آلية العرض

(1) ما هو العرض

العرض هو "نافذة" أخرى إلى المصفوفة الأصلية — تشارك نفس الذاكرة. تعديل العرض يُعدّل المصفوفة الأصلية مباشرة.

PYTHON
import numpy as np

a = np.array([1, 2, 3, 4, 5])
b = a[1:4]          # الشريحة تُرجع عرضاً
b[0] = 999
print(a)            # [  1 999   3   4   5]  تغيرت الأصلية!
print(b)            # [999   3   4]
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبت مسبقاً — قم بتثبيته محلياً (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.

ميزة العروض هي عدم النسخ — لا ذاكرة إضافية، سريعة جداً.

(2) علاقة الذاكرة

PYTHON
a = np.array([10, 20, 30])
b = a[:]            # عرض
print(a.__array_interface__['data'][0])  # عنوان بيانات الأصلية
print(b.__array_interface__['data'][0])  # عنوان بيانات العرض (نفس العنوان!)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبت مسبقاً — قم بتثبيته محلياً (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.

كلاهما يشير إلى نفس عنوان بداية الذاكرة — فقط البيانات الوصفية (الشكل، الخطوات) تختلف.

(3) الخاصية .base

PYTHON
a = np.arange(12).reshape(3, 4)
b = a[0:2, 1:3]  # شريحة — عرض
c = a[[0, 2]]    # فهرسة متقدمة — نسخة

print(b.base is a)  # True — عرض
print(c.base is a)  # False — نسخة


2. أي العمليات تُرجع عروضاً مقابل نسخ

(1) العروض (ذاكرة مشتركة، بدون نسخ)

العملية مثال
التقطيع الأساسي a[1:5], a[1:5:2], a[:, 2:4]
.view() a.view(np.float32)
reshape a.reshape(3, 4)
transpose / .T a.T, a.transpose(1, 0)
ravel (عادةً) a.ravel()
squeeze a.squeeze()
newaxis a[:, np.newaxis]

(2) النسخ (ذاكرة جديدة، مستقلة)

العملية مثال
.copy() a.copy()
الفهرسة المتقدمة a[[0, 2, 4]]
الفهرسة المنطقية a[a > 0]
astype a.astype(np.float32)
flatten a.flatten()
np.where np.where(a > 0, a, 0)

▶ مثال

TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبت مسبقاً — قم بتثبيته محلياً (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.

: التحقق من العرض مقابل النسخة باستخدام .base (الصعوبة ⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# شريحة أساسية — عرض
b = a[0:2]
print(f"slice base is a: {b.base is a}")  # True

---
## 3. إعادة تشكيل — عرض
c = a.reshape(6, 2)
print(f"reshape base is a: {c.base is a}")  # True

---
## 4. فهرسة متقدمة — نسخة
d = a[[0, 2]]
print(f"fancy base is a: {d.base is a}")  # False

---
## 5. فهرسة منطقية — نسخة
e = a[a > 5]
print(f"boolean base is a: {e.base is a}")  # False
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبت مسبقاً — قم بتثبيته محلياً (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.



6. جداول المقارنة

(1) شجرة قرار العرض مقابل النسخة

TEXT 📖 للعرض فقط
هل هو تقطيع أساسي (start:stop:step)؟
  ├── نعم → عرض (ذاكرة مشتركة)
  └── لا → هل هي فهرسة متقدمة/منطقية؟
      ├── نعم → نسخة (ذاكرة جديدة)
      └── لا → تحقق من الخاصية .base

(2) تأثير الأداء

العملية الزمن (مليون عنصر) الذاكرة
عرض (شريحة) O(1) مشتركة
نسخة (متقدمة) O(n) تخصيص جديد
.copy() O(n) تخصيص جديد
astype O(n) تخصيص جديد

▶ مثال: إعادة التشكيل والتحويل يُرجعان عروضاً (الصعوبة ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

---
## 7. إعادة التشكيل تُرجع عرضاً
b = a.reshape(6, 2)
print(f"reshape base is a: {b.base is a}")

---
## 8. التحويل يُرجع عرضاً
c = a.T
print(f"transpose base is a: {c.base is a}")

---
## 9. تعديل العرض يُغيّر الأصلية
c[0, 0] = 999
print(f"a[0, 0] after transpose mod: {a[0, 0]}")

المخرجات:

TEXT 📖 للعرض فقط
# تم التنفيذ بنجاح

المخرجات:

TEXT 📖 للعرض فقط
reshape base is a: True
transpose base is a: True
a[0, 0] after transpose mod: 999

▶ مثال: flatten مقابل ravel — نسخة مقابل عرض (الصعوبة ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

---
## 10. ravel عادةً يُرجع عرضاً
r = a.ravel()
print(f"ravel base is a: {r.base is a}")

---
## 11. flatten دائماً يُرجع نسخة
f = a.flatten()
print(f"flatten base is a: {f.base is a}")

---
## 12. بعد التحويل، قد يحتاج ravel إلى نسخ
t = a.T
r2 = t.ravel()
print(f"ravel of transposed base is a: {r2.base is a}")

المخرجات:

TEXT 📖 للعرض فقط
# تم التنفيذ بنجاح

المخرجات:

TEXT 📖 للعرض فقط
ravel base is a: True
flatten base is a: False
ravel of transposed base is a: False



❓ أسئلة شائعة

س كيف أتحقق مما إذا كانت المصفوفة عرضاً لأخرى؟
ج تحقق من arr.base is original. إذا كان True، فهو عرض. إذا كان arr.base هو None، فهي تملك بياناتها الخاصة.
س هل يمكنني إنشاء عرض بنوع بيانات مختلف؟
ج نعم — a.view(np.float32) يعيد تفسير نفس البايتات كنوع مختلف. هذا خطير ونادراً ما يكون مطلوباً. استخدم astype للحصول على نسخة آمنة مع تحويل.
س لماذا يُرجع ravel أحياناً نسخة؟
ج يُرجع ravel عرضاً فقط إذا كانت المصفوفة متجاورة في الذاكرة. بعد عمليات مثل التحويل، قد تصبح المصفوفة غير متجاورة، ويلجأ ravel إلى نسخة.
س متى يجب استخدام .copy()؟
ج (1) عندما تكون على وشك تعديل مصفوفة فرعية ولا تريد التأثير على الأصلية، (2) عندما تحتاج إلى مصفوفة متجاورة لعملية على مستوى C، (3) عندما تريد كسر رابط الذاكرة بشكل صريح.

📖 ملخص



📝 تمارين

  1. مبتدئ (الصعوبة ⭐): أنشئ مصفوفة أحادية البعد من 10 عناصر. أنشئ شريحة، وفهرسة متقدمة، واختيار قناع منطقي. لكل منها، تحقق مما إذا كان تعديل النتيجة يُغيّر الأصلية.

  2. متوسط (الصعوبة ⭐⭐): أنشئ مصفوفة 3x4، خذ شريحة 2x2، وعدّلها. لاحظ تغير الأصلية. الآن استخدم .copy() وكرر — تأكد من بقاء الأصلية دون تغيير.

  3. متقدم (الصعوبة ⭐⭐⭐): أنشئ مصفوفة ثلاثية الأبعاد، حولها، ثم حاول إعادة تشكيل النتيجة. تحقق مما إذا كانت إعادة التشكيل تُرجع عرضاً (استخدم .base). اشرح لماذا أو لم لا.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%