NumPy: أنواع البيانات dtype
آخر تحديث: 2026-08-26
أنواع البيانات dtype
1. ما ستتعلمه
- نظام dtype وتصنيفه
- إنشاء مصفوفات بأنواع محددة
- تحويل الأنواع ومخاطر الفيضان
- الأنواع المهيكلة
- مفاضلة الذاكرة/الدقة/السرعة لأنواع dtype
2. قصة
انخفضت دقة نموذج أليس من 95% إلى 12% بين ليلة وضحاها. السبب: تحويل float64 إلى int8 تسبب في فيضان جميع القيم فوق 127 إلى أرقام سالبة. "dtype ليس تفصيلًا بسيطًا — اختر النوع الخطأ وستتلف بياناتك."
3. المفاهيم الأساسية
(1) نظام dtype
dtype (نوع البيانات) في NumPy يصف نوع كل عنصر في المصفوفة. كل ndarray له خاصية .dtype.
np.int32 # عدد صحيح بإشارة 32 بت
np.float64 # نقطة عائمة 64 بت
np.bool_ # منطقي
np.str_ # سلسلة نصية يونيكود
np.object_ # كائن Python
dtype له حقلان:
| الحقل | المعنى | مثال |
|---|---|---|
kind |
فئة النوع | 'i'=int, 'f'=float, 'u'=uint, 'b'=bool |
itemsize |
بايت لكل عنصر | 4 لـ int32 |
import numpy as np
a = np.array([1, 2, 3])
print(a.dtype) # int64 (على منصات 64 بت)
print(a.dtype.kind) # 'i'
print(a.dtype.itemsize) # 8
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
(2) مقارنة الأنواع الصحيحة
| النوع | النطاق | بايت | الاسم المستعار |
|---|---|---|---|
int8 |
-128 ~ 127 | 1 | — |
int16 |
-32768 ~ 32767 | 2 | — |
int32 |
-2147483648 ~ 2147483647 | 4 | intp (32-bit) |
int64 |
-9223372036854775808 ~ 9223372036854775807 | 8 | intp (64-bit) |
uint8 |
0 ~ 255 | 1 | — |
uint16 |
0 ~ 65535 | 2 | — |
uint32 |
0 ~ 4294967295 | 4 | — |
uint64 |
0 ~ 18446744073709551615 | 8 | — |
(3) مقارنة الأنواع العائمة
| النوع | بايت | الدقة | الحد الأقصى | الحد الأدنى الموجب |
|---|---|---|---|---|
float16 |
2 | ~3 أرقام | 65504 | 5.96e-8 |
float32 |
4 | ~7 أرقام | 3.4e38 | 1.18e-38 |
float64 |
8 | ~15 رقمًا | 1.8e308 | 2.23e-308 |
float128 |
16 | ~33 رقمًا | 1.19e4932 | 3.36e-4932 |
float128 على العديد من المنصات هو في الواقع دقة ممتدة 80 بت محشوة إلى 128 بت، وليس 128 بت حقيقية.
(4) تحديد dtype
import numpy as np
---
## 4. بكائن نوع NumPy
a = np.array([1, 2, 3], dtype=np.float32)
---
## 5. بسلسلة نصية
b = np.array([1, 2, 3], dtype='float32')
---
## 6. برمز حرف واحد
c = np.array([1, 2, 3], dtype='f4') # float32: 'f' + 4 بايت
| الحرف | النوع | مثال |
|---|---|---|
b |
منطقي | np.dtype('b') |
i |
عدد صحيح بإشارة | np.dtype('i4') = int32 |
u |
عدد صحيح بدون إشارة | np.dtype('u1') = uint8 |
f |
عائم | np.dtype('f8') = float64 |
c |
مركب | np.dtype('c16') = complex128 |
S |
سلسلة بايت | np.dtype('S10') = سلسلة من 10 أحرف |
U |
سلسلة يونيكود | np.dtype('U5') = 5 أحرف يونيكود |
(5) تحويل الأنواع والفيضان
import numpy as np
---
## 7. astype يعيد مصفوفة جديدة بـ dtype الهدف
a = np.array([1, 2, 3], dtype=np.int32)
b = a.astype(np.float64) # [1. 2. 3.]
---
## 8. الفيضان: القيم التي تتجاوز النطاق تلتف
c = np.array([100, 200, 300], dtype=np.uint8)
---
## 9. [100, 200, 44] — 300 - 256 = 44
---
## 10. التحويل من عائم إلى صحيح يقصّر
d = np.array([1.9, 2.5, 3.1])
print(d.astype(np.int32)) # [1 2 3]
المخرجات: قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (
pip install numpy) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
(6) الأنواع المهيكلة
للبيانات الجدولية ذات الأنواع المختلطة، استخدم الأنواع المهيكلة:
import numpy as np
---
## 11. تعريف نوع مهيكل
dt = np.dtype([('name', 'U10'), ('age', 'i4'), ('salary', 'f8')])
---
## 12. إنشاء مصفوفة بنوع مهيكل
employees = np.array([
('Alice', 30, 75000.0),
('Bob', 25, 62000.0),
('Charlie', 35, 85000.0)
], dtype=dt)
print(employees['name']) # ['Alice' 'Bob' 'Charlie']
print(employees['salary'].mean()) # 74000.0
المخرجات: قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (
pip install numpy) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: توضيح الفيضان (الصعوبة ⭐⭐)
import numpy as np
---
## 13. نطاق int8: -128 إلى 127
vals = np.array([100, 120, 127, 128, 130, 200], dtype=np.int8)
print("int8 values:", vals)
---
## 14. [100 120 127 -128 -126 -56]
---
## 15. نطاق uint8: 0 إلى 255
vals_u = np.array([200, 255, 256, 300], dtype=np.uint8)
print("uint8 values:", vals_u)
---
## 16. [200 255 0 44]
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: نوع مهيكل — سجلات الموظفين (الصعوبة ⭐⭐)
import numpy as np
dt = np.dtype([('name', 'U10'), ('dept', 'U15'), ('salary', 'f8'), ('years', 'i2')])
data = np.array([
('Alice', 'Engineering', 95000, 5),
('Bob', 'Marketing', 72000, 3),
('Charlie', 'Engineering', 110000, 8),
('Diana', 'Sales', 68000, 2),
], dtype=dt)
---
## 17. استعلام حسب القسم
eng = data[data['dept'] == 'Engineering']
print("Engineering avg salary:", eng['salary'].mean())
---
## 18. ترتيب حسب الراتب
sorted_data = np.sort(data, order='salary')
print("Top earner:", sorted_data[-1]['name'], sorted_data[-1]['salary'])
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
19. جداول المقارنة
(1) قواعد تحويل الأنواع
| المصدر ↓ / الهدف → | int | float | complex | سلسلة |
|---|---|---|---|---|
| int | ✅ | ✅ (آمن) | ✅ (آمن) | ✅ (عشري) |
| float | ⚠️ يقصّر | ✅ | ✅ (آمن) | ✅ (عشري) |
| complex | ⚠️ يفقد التخيلي | ⚠️ يفقد التخيلي | ✅ | ✅ (نصي) |
| bool | ✅ (0/1) | ✅ (0.0/1.0) | ✅ | ✅ |
(2) مصفوفة الذاكرة مقابل الدقة
| dtype | 1M عنصر | نسبة إلى float64 | حالة الاستخدام |
|---|---|---|---|
| float16 | 2 MB | 25% | تدريب GPU، تخزين |
| float32 | 4 MB | 50% | تعلم عميق، معظم ML |
| float64 | 8 MB | 100% | حوسبة علمية |
| int8 | 1 MB | 12.5% | بايتات الصور، أعلام |
| int32 | 4 MB | 50% | أعداد صحيحة عامة |
| int64 | 8 MB | 100% | فهارس كبيرة، طوابع زمنية |
(3) سلوك الفيضان
| العملية | int8 | uint8 | float32 |
|---|---|---|---|
| الحد الأقصى + 1 | -128 (التفاف) | 0 (التفاف) | inf |
| الحد الأدنى - 1 | 127 (التفاف) | 255 (التفاف) | -inf |
| 0 / 0 | خطأ | خطأ | nan |
20. مخطط المبدأ
graph TB
A[كائن Python] --> B{استنتاج dtype}
B -->|int| C[int64]
B -->|float| D[float64]
B -->|mixed| E[رفع إلى النوع المشترك]
B -->|explicit| F[نوع يحدده المستخدم]
C --> G[ndarray بنوع ثابت]
D --> G
E --> G
F --> G
G --> H[عمليات متجهة]
G --> I[تخزين موفر للذاكرة]
style A fill:#e1f5fe
style G fill:#c8e6c9
style H fill:#fff9c4
style I fill:#fff9c4
▶ مثال: تحويل dtype واستخدام الذاكرة (الصعوبة ⭐⭐)
import numpy as np
---
## 21. مقارنة استخدام الذاكرة لأنواع مختلفة
arr_int64 = np.ones(1000000, dtype=np.int64)
arr_float32 = np.ones(1000000, dtype=np.float32)
arr_int8 = np.ones(1000000, dtype=np.int8)
print(f"int64: {arr_int64.nbytes / 1e6:.1f} MB")
print(f"float32: {arr_float32.nbytes / 1e6:.1f} MB")
print(f"int8: {arr_int8.nbytes / 1e6:.1f} MB")
---
## 22. تحويل بين الأنواع
converted = arr_float32.astype(np.int32)
print(f"Converted dtype: {converted.dtype}")
المخرجات:
# تم التنفيذ بنجاح
المخرجات:
TEXT 📖 للعرض فقطint64: 8.0 MB float32: 4.0 MB int8: 1.0 MB Converted dtype: int32
❓ أسئلة شائعة
int64 على منصات 64 بت، int32 على منصات 32 بت. NumPy يختار بناءً على بنية نظامك. يمكنك دائمًا التحديد صراحة باستخدام dtype=np.int32.int8(127) + 1 = -128. هذا مصدر شائع للأخطاء. استخدم np.seterr(over='warn') لاكتشافه.float و double.object (الذي يخزن مراجع كائنات Python، مما يفقد الأداء).📖 ملخص
- dtype يحدد نوع العنصر لكل ndarray، مع حقلي
kind(الفئة) وitemsize(بايت) - الأنواع الصحيحة: int8/16/32/64، uint8/16/32/64 — الفيضان يلتف بصمت
- الأنواع العائمة: float16/32/64/128 — بايت أكثر = دقة أكثر + ذاكرة أكثر
- حدد dtype عبر
np.dtype()، كائنات النوع، سلاسل نصية، أو رموز أحرف واحدة astype()يحول بين الأنواع؛ الفيضان يلتف، التحويل من عائم لصحيح يقصّر- الأنواع المهيكلة تمكن البيانات الجدولية مختلطة الأنواع داخل ndarray واحد
📝 تمارين
-
مبتدئ (الصعوبة ⭐): أنشئ مصفوفات من أنواع int8، int16، int32، int64، float32، float64 — كل منها بـ 1000 عنصر قيمتها 1. اطبع
nbytesلكل منها واشرح الفروق في الذاكرة. -
متوسط (الصعوبة ⭐⭐): أنشئ مصفوفة uint8 بالقيم [0, 127, 128, 255, 256, -1]. لاحظ أي القيم تفيض واشرح النتائج. ثم أنشئ نوعًا مهيكلًا لفهرس كتب بحقول: title (نص)، author (نص)، year (int16)، price (float32).
-
متقدم (الصعوبة ⭐⭐⭐): حول مصفوفة float64 من مليون رقم عشوائي إلى float32، ثم عد إلى float64. احسب متوسط الخطأ المطلق بين المصفوفة الأصلية والمصفوفة بعد الرحلة ذهابًا وإيابًا. كرر مع float16. سجل فقدان الدقة لكل نوع.