NumPy: عمليات الشكل

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

عمليات الشكل

1. ما ستتعلمه




2. قصة حقيقية لمطور

(1) المشكلة

بوب يعيد تشكيل 12 نقطة بيانات من 3×4 إلى 4×3، معتقدًا أنه "يعيد ترتيب الذاكرة" — لكن كل إعادة تشكيل كانت تنسخ البيانات، مما يقتل سرعته وذاكرته.

(2) الحل

أليس تظهر له مخطط Mermaid: "reshape يغير البيانات الوصفية فقط — ولا يتحرك بايت واحد من البيانات. هذا هو سر سرعة NumPy." طالما أن العملية تعيد عرضًا، لا يتم نسخ أي بيانات.

(3) النتيجة

بمجرد أن فهم بوب "عرض مقابل نسخة"، استخدم كود عمليات الشكل قدرًا أقل من الذاكرة بعشر مرات وكان أسرع بعدة مرات. flatten فقط هي التي تنسخ فعلًا؛ كل شيء آخر — reshape، ravel، transpose، swapaxes — هو عرض.




3. عمليات الشكل بالتفصيل

(1) كيف يعمل reshape

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

PYTHON
import numpy as np

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

print(a.shape)   # (12,)
print(b.shape)   # (3, 4)
print(b.base is a)  # True — b هو عرض لـ a
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.

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

مخطط ذاكرة reshape

100%
graph LR
    A["المصفوفة الأصلية<br/>shape=(12,)"] -->|"reshape(3,4)"| B["عرض<br/>shape=(3,4)"]
    A -->|"reshape(4,3)"| C["عرض<br/>shape=(4,3)"]
    A -->|"reshape(2,6)"| D["عرض<br/>shape=(2,6)"]

    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.

النقطة الرئيسية: A، B، C، و D جميعها تشارك نفس الذاكرة — فقط "تفسرها" بشكل مختلف.


(2) الاستدلال التلقائي بـ -1

استخدم -1 في reshape لترك NumPy يحسب حجم ذلك البعد تلقائيًا.

PYTHON
a = np.arange(12)

---
## 5. NumPy يستنتج: 12 / 3 = 4
b = a.reshape(3, -1)     # shape = (3, 4)
c = a.reshape(2, -1)     # shape = (2, 6)
d = a.reshape(-1, 6)     # shape = (2, 6)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.

(3) flatten vs ravel

الطريقة الإرجاع ينسخ؟ الذاكرة
ndarray.flatten() مصفوفة 1D ينسخ دائمًا ذاكرة جديدة
ndarray.ravel() مصفوفة 1D عرض عندما يمكن عادة مشتركة
PYTHON
import numpy as np

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

f = a.flatten()  # دائمًا نسخة
r = a.ravel()    # عادة عرض

f[0] = 999
print(a[0, 0])   # 0 — f نسخة، a لم يتغير

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

(4) transpose و .T

PYTHON
import numpy as np

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

b = a.T          # تحويل — عرض، لا نسخ
print(b.shape)   # (4, 3)

---
## 6. للمصفوفات متعددة الأبعاد، transpose يقبل ترتيب المحاور
c = a.transpose(1, 0)
print(c.shape)   # (4, 3)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.

(5) newaxis و squeeze

PYTHON
import numpy as np

a = np.array([1, 2, 3])       # shape (3,)

---
## 7. newaxis يضيف بُعدًا
b = a[np.newaxis, :]           # shape (1, 3)
c = a[:, np.newaxis]           # shape (3, 1)
d = a[np.newaxis, :, np.newaxis]  # shape (1, 3, 1)

---
## 8. squeeze يزيل الأبعاد ذات الحجم 1
e = np.squeeze(d)              # shape (3,) — العودة إلى الأصل
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.


▶ مثال

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

: reshape مع الاستدلال التلقائي -1 (الصعوبة ⭐)

PYTHON
import numpy as np

a = np.arange(24)

---
## 9. استخدم -1 للاستدلال التلقائي
b = a.reshape(2, -1)      # 2 x 12
c = a.reshape(3, -1)      # 3 x 8
d = a.reshape(4, -1)      # 4 x 6
e = a.reshape(6, -1)      # 6 x 4

print(f"a.shape={a.shape}")
print(f"b.shape={b.shape}")  # (2, 12)
print(f"c.shape={c.shape}")  # (3, 8)
print(f"d.shape={d.shape}")  # (4, 6)
print(f"e.shape={e.shape}")  # (6, 4)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.

▶ مثال

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

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

PYTHON
import numpy as np

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

---
## 10. flatten تنسخ دائمًا
flat = a.flatten()
flat[0] = 999
print("After flat[0]=999, a[0,0]=", a[0,0])  # 0 (لم يتغير)

---
## 11. ravel عادة تعيد عرضًا
rav = a.ravel()
rav[0] = 999
print("After rav[0]=999, a[0,0]=", a[0,0])  # 999 (تغير!)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.

▶ مثال

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

: transpose و newaxis (الصعوبة ⭐⭐)

PYTHON
import numpy as np

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

---
## 12. تحويل
print("Original shape:", a.shape)     # (3, 4)
print("Transposed shape:", a.T.shape)  # (4, 3)

---
## 13. newaxis: إضافة أبعاد
row = np.array([1, 2, 3])
print("row shape:", row.shape)                # (3,)
print("row[np.newaxis,:] shape:", row[np.newaxis, :].shape)  # (1, 3)
print("row[:,np.newaxis] shape:", row[:, np.newaxis].shape)  # (3, 1)
TEXT 📖 للعرض فقط
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
⚠️ ملاحظة: الكود أدناه يحتاج إلى التشغيل في بيئة Python محلية.




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

(1) ملخص عمليات الشكل

العملية الإرجاع ينسخ البيانات؟ حالة الاستخدام
reshape عرض لا تغيير الشكل
flatten نسخة نعم تحويل آمن لـ 1D
ravel عرض (عادة) نادرًا 1D سريع
T / transpose عرض لا إعادة ترتيب المحاور
newaxis عرض لا إضافة بُعد
squeeze عرض لا إزالة أبعاد بحجم 1
swapaxes عرض لا تبديل محورين

(2) عرض مقابل نسخة

الميزة عرض نسخة
الذاكرة مشتركة تخصيص جديد
التعديل يؤثر على الأصل مستقل
السرعة O(1) O(n)
خاصية base يشير إلى الأصل لا شيء
متى تستخدم قراءة فقط أو مشاركة مقصودة تعديل آمن



15. مخطط المبدأ

100%
graph TB
    A["الأصل (12,)"] -->|reshape/flatten/ravel| B["شكل جديد"]
    A --> C["مخزن البيانات: [0 1 2 ... 11]"]
    B --> C
    B -->|flatten| D["نسخة من مخزن البيانات"]
    B -->|ravel| C
    B -->|transpose| C
    B -->|newaxis| C
    
    style A fill:#4CAF50,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#E91E63,color:#fff



❓ أسئلة شائعة

س هل reshape يعيد عرضًا دائمًا؟
ج دائمًا تقريبًا — طالما أن المصفوفة متجاورة في الذاكرة. إذا كانت المصفوفة غير متجاورة (مثل بعد transpose)، قد يحتاج reshape إلى النسخ. استخدم np.ascontiguousarray() أولاً إذا لزم الأمر.
س ما الفرق بين .T و .transpose()؟
ج .T هو اختصار لعكس جميع المحاور (مكافئ لـ .transpose() بترتيب معكوس). للمصفوفات ثنائية الأبعاد هما متطابقان. للأبعاد 3+، .T يعكس جميع المحاور، بينما .transpose(1,0,2) يسمح لك بتحديد الترتيب.
س متى يجب استخدام flatten vs ravel؟
ج إذا كنت ستعدل النتيجة أحادية البعد ولا تريد التأثير على الأصل، استخدم flatten (نسخة آمنة). إذا كنت تقرأ فقط أو تريد نشر التغييرات، استخدم ravel (أسرع، عادة عرض).
س ماذا يعني -1 في reshape؟
ج يخبر NumPy بـ "احسب هذا البعد تلقائيًا." يُسمح بـ -1 واحد فقط. NumPy يحسبه كـ total_size / product_of_other_dims.

📖 ملخص



📝 تمارين

  1. مبتدئ (الصعوبة ⭐): أنشئ مصفوفة من 20 عنصرًا، أعد تشكيلها إلى (4,5)، (5,4)، (2,10)، و (10,2) باستخدام -1. تحقق من صحة جميع الأشكال.

  2. متوسط (الصعوبة ⭐⭐): أنشئ مصفوفة 3x4، حولها، ثم حاول إعادة تشكيل النتيجة المحولة. هل لا يزال reshape يتجنب النسخ؟ تحقق باستخدام .base.

  3. متقدم (الصعوبة ⭐⭐⭐): أنشئ مصفوفة ثلاثية الأبعاد بالشكل (2,3,4). استخدم transpose(2,0,1) لإعادة ترتيب المحاور. اشرح ما يمثله كل بُعد في النتيجة. ثم استخدم swapaxes لتحقيق نفس النتيجة.

Web-Tutorial.com

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

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

100%