NumPy: عمليات الشكل
آخر تحديث: 2026-08-26
عمليات الشكل
1. ما ستتعلمه
- ❶ reshape لا ينسخ البيانات — يغير البيانات الوصفية فقط
- ❷
-1يستنتج حجم البعد تلقائيًا - ❸ flatten مقابل ravel: نسخة مقابل عرض
- ❹ transpose / .T تحويل المصفوفة
- ❺ newaxis لإضافة أبعاد، squeeze لإزالتها
2. قصة حقيقية لمطور
(1) المشكلة
بوب يعيد تشكيل 12 نقطة بيانات من 3×4 إلى 4×3، معتقدًا أنه "يعيد ترتيب الذاكرة" — لكن كل إعادة تشكيل كانت تنسخ البيانات، مما يقتل سرعته وذاكرته.
(2) الحل
أليس تظهر له مخطط Mermaid: "reshape يغير البيانات الوصفية فقط — ولا يتحرك بايت واحد من البيانات. هذا هو سر سرعة NumPy." طالما أن العملية تعيد عرضًا، لا يتم نسخ أي بيانات.
(3) النتيجة
بمجرد أن فهم بوب "عرض مقابل نسخة"، استخدم كود عمليات الشكل قدرًا أقل من الذاكرة بعشر مرات وكان أسرع بعدة مرات. flatten فقط هي التي تنسخ فعلًا؛ كل شيء آخر — reshape، ravel، transpose، swapaxes — هو عرض.
3. عمليات الشكل بالتفصيل
(1) كيف يعمل reshape
reshape يغير شكل المصفوفة لكنه لا ينسخ البيانات. يعدل فقط البيانات الوصفية للمصفوفة (الشكل والخطوات)؛ البيانات الخام في الذاكرة تبقى مكانها.
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
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
---
## 4. reshape لا ينسخ البيانات
b[0, 0] = 999
print(a[0]) # 999 — تعديل b يغير a!
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
مخطط ذاكرة reshape
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
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
النقطة الرئيسية: A، B، C، و D جميعها تشارك نفس الذاكرة — فقط "تفسرها" بشكل مختلف.
(2) الاستدلال التلقائي بـ -1
استخدم -1 في reshape لترك NumPy يحسب حجم ذلك البعد تلقائيًا.
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)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
(3) flatten vs ravel
| الطريقة | الإرجاع | ينسخ؟ | الذاكرة |
|---|---|---|---|
ndarray.flatten() |
مصفوفة 1D | ينسخ دائمًا | ذاكرة جديدة |
ndarray.ravel() |
مصفوفة 1D | عرض عندما يمكن | عادة مشتركة |
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 تغير
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
(4) transpose و .T
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)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
(5) newaxis و squeeze
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,) — العودة إلى الأصل
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: reshape مع الاستدلال التلقائي -1 (الصعوبة ⭐)
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)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: flatten vs ravel — نسخة مقابل عرض (الصعوبة ⭐⭐)
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 (تغير!)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: transpose و newaxis (الصعوبة ⭐⭐)
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)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
14. جداول المقارنة
(1) ملخص عمليات الشكل
| العملية | الإرجاع | ينسخ البيانات؟ | حالة الاستخدام |
|---|---|---|---|
reshape |
عرض | لا | تغيير الشكل |
flatten |
نسخة | نعم | تحويل آمن لـ 1D |
ravel |
عرض (عادة) | نادرًا | 1D سريع |
T / transpose |
عرض | لا | إعادة ترتيب المحاور |
newaxis |
عرض | لا | إضافة بُعد |
squeeze |
عرض | لا | إزالة أبعاد بحجم 1 |
swapaxes |
عرض | لا | تبديل محورين |
(2) عرض مقابل نسخة
| الميزة | عرض | نسخة |
|---|---|---|
| الذاكرة | مشتركة | تخصيص جديد |
| التعديل | يؤثر على الأصل | مستقل |
| السرعة | O(1) | O(n) |
خاصية base |
يشير إلى الأصل | لا شيء |
| متى تستخدم | قراءة فقط أو مشاركة مقصودة | تعديل آمن |
15. مخطط المبدأ
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
❓ أسئلة شائعة
np.ascontiguousarray() أولاً إذا لزم الأمر..T هو اختصار لعكس جميع المحاور (مكافئ لـ .transpose() بترتيب معكوس). للمصفوفات ثنائية الأبعاد هما متطابقان. للأبعاد 3+، .T يعكس جميع المحاور، بينما .transpose(1,0,2) يسمح لك بتحديد الترتيب.total_size / product_of_other_dims.📖 ملخص
- reshape يغير فقط بيانات الشكل/الخطوات الوصفية — لا نسخ بيانات، عملية O(1)
-1يستنتج حجم البعد تلقائيًا من العدد الإجمالي للعناصر- flatten تنسخ دائمًا؛ ravel عادة تعيد عرضًا (تحقق من
.base) - transpose/T/swapaxes تعيد عروضًا بخطوات معدلة، بدون نقل بيانات
- newaxis يضيف بُعدًا بحجم 1؛ squeeze يزيل الأبعاد بحجم 1
- فهم الفرق بين العرض والنسخة هو مفتاح كتابة كود NumPy موفر للذاكرة
📝 تمارين
-
مبتدئ (الصعوبة ⭐): أنشئ مصفوفة من 20 عنصرًا، أعد تشكيلها إلى (4,5)، (5,4)، (2,10)، و (10,2) باستخدام
-1. تحقق من صحة جميع الأشكال. -
متوسط (الصعوبة ⭐⭐): أنشئ مصفوفة 3x4، حولها، ثم حاول إعادة تشكيل النتيجة المحولة. هل لا يزال reshape يتجنب النسخ؟ تحقق باستخدام
.base. -
متقدم (الصعوبة ⭐⭐⭐): أنشئ مصفوفة ثلاثية الأبعاد بالشكل (2,3,4). استخدم
transpose(2,0,1)لإعادة ترتيب المحاور. اشرح ما يمثله كل بُعد في النتيجة. ثم استخدمswapaxesلتحقيق نفس النتيجة.