import numpy as np
= np.array([1, 2, 3])
a = np.array([4, 5, 6])
b print(np.dot(a, b))
32
عندما يكبر النص البرمجي ويتعقد، نلجأ لتقسيمه في ملفات منفصلة تؤدي كل منها وظيفة محددة. وذلك حتى يسهل فهم البرنامج، ويسهل التعديل عليه والإضافة.
أو قد نرى أن جزءًا من النص البرمجي يستحق الاستعمال في مشروع آخر، فنريد أن نلفَّه في حزمة، ونصدِّره ليكون قابلاً للتثبيت في مشاريع أخرى.
هاتان الحالتان تستوجبان أن نتعرف على مصطلحين في بايثون: الوحدة والحزمة.
الوِحدة (Module) هي النص البرمجي في الملف الواحد (مثل: script.py
)
الحزمة (Package) هي مجموعة مكوَّنة من وِحدة أو أكثر؛ وتُعرَّف: بمجلَّد يكون فيه ملف خاص باسم __init.py__
ويوضع فيه النص البرمجي المنشئ الذي يعمل عند فعل استيراد الحزمة بالكلمة import
(في المرة الأولى فقط).
فيما يلي مثال يوضِّح ترتيب حزمة ما (my_package
) مكوَّنة من حزم مضمَّنة، وفي المستوى الأخير نرى الوحدات، على النحو التالي:
│───main.py
│
└───my_package
│ __init__.py
│
├───pkg1
│ │ __init__.py
│ │ module_a.py
│ │ module_b.py
│
├───pkg2
│ │ __init__.py
│ │ module_a.py
│ │ module_b.py
│ │ module_c.py
main.py
فيه الإجراء الأوَّل الذي يمثِّل مدخل البرنامج. ومنه سنستعمل عبارات الاستيراد (import
).pkg1
وpkg2
هما: حزم فرعية من حزمة my_package
، ويمكن استيرادهما بشكل مستقل.module_a.py
وmodule_b.py
وmodule_c.py
هي وحدات داخل الحزم الفرعية.__init__.py
على أنه علامةً للمجلَّد الذي هو فيه أنه حزمة؛ ولا يلزم أن يتضمن أي أوامر برمجية، ولكنه غالبًا ما يحتوي على تعليمات تهيئة للحزمة. ولذلك سميت init
من الإنجليزية Initialization بمعنى التهيئة.دعنا نلقي نظرة على عمليات الاستيراد واحدة تلو الأخرى، انظر (main.py
):
import my_package
from my_package.pkg1 import module_a
from my_package.pkg2.module_a import func_a
from my_package.pkg2.module_b import *
أولاً، لاحظ أن فعل الاستيراد import my_package
يحدد حزمة لا وِحدة. وبالتالي، سينفذ الملف __init__.py
، الذي يحتوي على عبارات تعيين (مثل __version__
، وDEFAULT_TIMEOUT
، وما إلى ذلك) سترتبط بمعرف my_package
، ويمكن الوصول إليها باستخدام النقطة (.
).
ثانيًا لاحظ العبارة: from my_package.pkg1 import module_a
فهي تحدد وحدة (module_a
)، وبالتالي، يتم تنفيذ جميع التعليمات البرمجية في module_a.py
والتعيينات تُسنَد للمعرف module_a
ويمكن الوصول إليها باستخدام النقطة (.
).
ثالثًا استيراد مباشر للإجراء func_a
من وحدة module_a
في الحزمة الفرعية pkg2
.
أخيرًا الصيغة from ... import *
تستورد جميع (*
) الأسماء من الوحدة النمطية (باستثناء تلك التي تبدأ بـ بالشرطتين السفليتين: __
) إلى نطاق التسمية الحالي (في الوحدة التي نحن فيها). بشكل عام، لا ننصح باستعمال هذه الطريقة، حيث قد تؤدي إلى إلغاء أسماء سبق تعريفها لتحل مكانها هذه الأسماء الجديدة، ولكن لا بأس بها لتقليل جهد الكتابةخصوصًا في الجلسات التفاعلية.
حين لا تجد بايثون اسم الحزمة حاضرًا، فإنها تلجأ إلى البحث في الحزم التي تم تنزيلها وتثبيتها. ولأننا نستعمل uv
حيث هو مدير حزم يحافظ على خصوصية الحزم المثبتة لكل مشروع بشكل منفصل، فإننا سنجدها داخل .venv/
، وتحديدًا داخل المجلد: .venv/lib/python3.12/site-packages
(في حال كنا نستعمل الإصدار 3.12 من بايثون).
لتثبيت حزمة من قاعدة بيانات الحزم PyPI نستعمل أداة uv
على النحو التالي:
أولاً باستعمال أداة uv
:
uv add numpy
وبعد تثبيت الحزمة ، نستوردها هكذا ونستعملها:
import numpy as np
= np.array([1, 2, 3])
a = np.array([4, 5, 6])
b print(np.dot(a, b))
32
وستجد أن حزمة numpy
أصبحت في هذا المجلد: .venv/lib/python3.12/site-packages/numpy