الفصل الحادي عشر: مكتبة بايثون القياسية – أدواتك المدمجة
مقدمة الفصل
تخيل أنك تبني منزلاً. بايثون، كلغة، تعطيك الأدوات الأساسية: مطرقة، منشار، ومسامير (أي، if
, for
, def
). يمكنك بناء هيكل المنزل بهذه الأدوات. لكن ماذا عن السباكة، الكهرباء، أو طلاء الجدران؟ هل يجب عليك صناعة كل الأنابيب والأسلاك والدهانات من الصفر؟ بالطبع لا.
هنا يأتي دور مكتبة بايثون القياسية (Python Standard Library). إنها مثل متجر ضخم للأدوات والتجهيزات الجاهزة. تحتاج إلى أدوات سباكة؟ أحضر “صندوق أدوات الوقت والتاريخ”. تحتاج إلى تجهيزات كهربائية؟ أحضر “صندوق أدوات نظام التشغيل”.
هذه “الصناديق” هي ما نسميه الوحدات (Modules). في هذا الفصل، سنتعلم كيف “نستورد” هذه الوحدات إلى برنامجنا ونستخدم أدواتها الجاهزة لأداء مهام متخصصة، مما يوفر علينا وقتًا وجهدًا هائلين.
1. ما هي الوحدة وكيف نستخدمها؟
الوحدة (Module): هي ببساطة ملف بايثون (.py
) يحتوي على دوال، كلاسات، ومتغيرات جاهزة للاستخدام، تم كتابتها بواسطة مطوري بايثون لتؤدي مهامًا محددة.
الطريقة الأساسية للاستيراد: import
الوصف:
لاستخدام أي وحدة، يجب أولاً “استيرادها” في بداية ملفك باستخدام الكلمة المفتاحية import
. هذا الأمر يشبه إحضار صندوق أدوات كامل إلى ورشة عملك.
# لاستخدام وحدة الرياضيات، يجب استيرادها أولاً
import math
# للوصول إلى أداة داخل الوحدة، نكتب اسم الوحدة، نقطة، ثم اسم الأداة
# math.pi هو ثابت (متغير) معرف مسبقًا داخل وحدة math
print(f"قيمة الثابت باي (pi) هي: {math.pi}")
# استخدام دالة الجذر التربيعي من الوحدة
root = math.sqrt(64)
print(f"الجذر التربيعي للرقم 64 هو: {root}")
الشرح:
بعد import math
، أصبح بإمكاننا الوصول إلى أي شيء داخل وحدة math
عن طريق كتابة math.
أولاً. هذا يمنع تضارب الأسماء بين أدواتك وأدوات الوحدات الأخرى.
طرق أخرى للاستيراد
استيراد أداة محددة: from ... import ...
الوصف: بدلاً من إحضار صندوق الأدوات بالكامل، يمكنك إحضار أداة واحدة محددة منه. هذا يتيح لك استخدام الأداة مباشرة بدون كتابة اسم الوحدة في كل مرة.
# استيراد دالة sqrt والثابت pi فقط من وحدة math
from math import sqrt, pi
# الآن يمكننا استخدامهما مباشرة
print(f"قيمة باي هي: {pi}")
root_of_81 = sqrt(81)
print(f"الجذر التربيعي للرقم 81 هو: {root_of_81}")
الشرح: هذه الطريقة مفيدة عندما تحتاج إلى أداة أو اثنتين بشكل متكرر، وتجعل الكود أقصر قليلاً.
إعطاء اسم مستعار للوحدة: import ... as ...
الوصف: أحيانًا تكون أسماء الوحدات طويلة. يمكنك إعطاؤها اسمًا مستعارًا (alias) أقصر لتسهيل الكتابة.
# استيراد وحدة datetime وإعطائها الاسم المستعار dt
import datetime as dt
# الآن نستخدم الاسم المستعار dt بدلاً من datetime
current_time = dt.datetime.now()
print(f"الوقت الحالي هو: {current_time}")
الشرح:
هذه ممارسة شائعة جدًا، خاصة مع مكتبات البيانات مثل pandas
التي يتم استيرادها عادة كـ pd
.
2. كيف تكتشف ما بداخل الوحدة؟
لا يمكن لأحد أن يحفظ كل الدوال في كل الوحدات. الأهم هو أن تتعلم كيف تستكشفها بنفسك.
- دالة
dir()
: تعطيك قائمة بكل الأسماء (دوال، متغيرات، كلاسات) الموجودة داخل وحدة ما. - دالة
help()
: تعطيك شرحًا مفصلاً (من الـ docstring) عن وظيفة أي دالة أو وحدة.
import random
# اكتشف ما بداخل وحدة random
# print(dir(random)) # ستطبع قائمة طويلة من الأسماء
# احصل على مساعدة حول دالة محددة مثل randint
help(random.randint)
الناتج من help(random.randint)
سيكون:
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
3. استكشاف وحدات قياسية مهمة
أ. وحدة math
: للعمليات الرياضية
الوصف: توفر هذه الوحدة دوالًا رياضية متقدمة لا توفرها العمليات الحسابية الأساسية.
import math
# حساب الجذر التربيعي
print(f"الجذر التربيعي لـ 81 هو: {math.sqrt(81)}")
# الرفع إلى قوة (2 أس 4)
print(f"2 مرفوع للقوة 4 هو: {math.pow(2, 4)}")
# تقريب الرقم لأعلى ولأسفل
print(f"تقريب 4.2 لأعلى: {math.ceil(4.2)}") # ceil -> ceiling (سقف)
print(f"تقريب 4.8 لأسفل: {math.floor(4.8)}") # floor (أرضية)
ب. وحدة random
: للعشوائية
الوصف: هذه الوحدة أساسية في بناء الألعاب، والمحاكاة، أو عند الحاجة إلى اختيار عينات عشوائية.
import random
# توليد عدد صحيح عشوائي بين 1 و 6 (مثل حجر النرد)
dice_roll = random.randint(1, 6)
print(f"رمية النرد: {dice_roll}")
# توليد عدد عشري عشوائي بين 0 و 1
random_float = random.random()
print(f"عدد عشري عشوائي: {random_float}")
# اختيار عنصر عشوائي من قائمة
players = ["أحمد", "سارة", "علي", "فاطمة"]
winner = random.choice(players)
print(f"الفائز هو: {winner}")
# خلط ترتيب عناصر قائمة بشكل عشوائي
cards = ["A", "K", "Q", "J"]
random.shuffle(cards)
print(f"البطاقات بعد الخلط: {cards}")
ج. وحدة datetime
: للتعامل مع الوقت والتاريخ
الوصف: هذه الوحدة لا غنى عنها عند التعامل مع أي بيانات تتعلق بالوقت، مثل تسجيل وقت حدوث عملية ما أو حساب المدد الزمنية.
import datetime as dt
# الحصول على الوقت والتاريخ الحاليين
current_moment = dt.datetime.now()
print(f"الوقت والتاريخ الحاليان: {current_moment}")
# الحصول على تاريخ اليوم فقط
today_date = dt.date.today()
print(f"تاريخ اليوم هو: {today_date}")
# تنسيق الوقت والتاريخ في نص مقروء
# %Y = السنة الكاملة, %m = الشهر, %d = اليوم, %H = الساعة (24), %M = الدقيقة, %S = الثانية
formatted_time = current_moment.strftime("%Y-%m-%d %H:%M:%S")
print(f"الوقت المنسق: {formatted_time}")
# حساب تاريخ مستقبلي
one_week_from_now = current_moment + dt.timedelta(weeks=1)
print(f"التاريخ بعد أسبوع من الآن سيكون: {one_week_from_now.date()}")
د. وحدتا os
و pathlib
: للتفاعل مع نظام التشغيل
الوصف:
تسمح لك هذه الوحدات بالقيام بعمليات تتعلق بنظام التشغيل، مثل التعامل مع الملفات والمجلدات والمسارات. وحدة pathlib
هي الطريقة الأحدث والموصى بها للتعامل مع المسارات.
import os
from pathlib import Path
# --- باستخدام وحدة os ---
# الحصول على مجلد العمل الحالي
current_directory_os = os.getcwd()
print(f"مجلد العمل الحالي (باستخدام os): {current_directory_os}")
# --- باستخدام وحدة pathlib (الطريقة الحديثة) ---
# إنشاء كائن مسار يمثل المجلد الحالي
current_directory_path = Path.cwd() # cwd = Current Working Directory
print(f"مجلد العمل الحالي (باستخدام pathlib): {current_directory_path}")
# إنشاء مسار لملف جديد بطريقة آمنة تعمل على كل الأنظمة
file_path = current_directory_path / "reports" / "report.txt"
print(f"المسار الكامل للملف الجديد: {file_path}")
4. تمرين تطبيقي: لعبة تخمين الرقم
المطلوب:
بناء لعبة بسيطة حيث يقوم الكمبيوتر باختيار رقم سري بين 1 و 100، ويحاول المستخدم تخمينه. يجب على البرنامج إعطاء تلميحات للمستخدم إذا كان تخمينه أعلى أو أقل من اللازم.
إرشادات الحل:
- استيراد الوحدة: ستحتاج إلى وحدة
random
لاختيار الرقم السري. - توليد الرقم السري: استخدم
random.randint(1, 100)
لتوليد الرقم وتخزينه في متغير. - حلقة لا نهائية: استخدم حلقة
while True
لتستمر اللعبة حتى يخمن المستخدم الرقم الصحيح. - طلب إدخال المستخدم: اطلب من المستخدم إدخال تخمينه. لا تنسَ معالجة الأخطاء باستخدام
try...except
في حال أدخل المستخدم نصًا بدلاً من رقم. - المقارنة: استخدم
if/elif/else
لمقارنة تخمين المستخدم بالرقم السري وإعطاء التلميح المناسب (“أعلى”، “أقل”، أو “صحيح”). - إنهاء اللعبة: إذا كان التخمين صحيحًا، اطبع رسالة تهنئة واستخدم
break
للخروج من الحلقة.
الحل المقترح:
# --- لعبة تخمين الرقم ---
# 1. استيراد وحدة random
import random
# 2. توليد رقم سري بين 1 و 100
secret_number = random.randint(1, 100)
print("لقد اخترت رقمًا سريًا بين 1 و 100. هل يمكنك تخمينه؟")
print("--- بدء اللعبة ---")
# 3. استخدام حلقة while True لاستقبال التخمينات
while True:
try:
# 4. طلب تخمين المستخدم وتحويله إلى رقم
user_guess_str = input("أدخل تخمينك: ")
user_guess = int(user_guess_str)
# 5. مقارنة التخمين بالرقم السري
if user_guess < secret_number:
print("تخمينك أقل من اللازم. حاول رقمًا أكبر!")
elif user_guess > secret_number:
print("تخمينك أعلى من اللازم. حاول رقمًا أصغر!")
else:
# 6. في حال التخمين الصحيح
print(f"🎉 تهانينا! لقد خمنت الرقم الصحيح وهو {secret_number}.")
break # إنهاء اللعبة
except ValueError:
print("خطأ: الرجاء إدخال رقم صحيح فقط.")
5. خلاصة الفصل
- مكتبة بايثون القياسية هي كنز من الوحدات (Modules) الجاهزة التي تسرّع عملية التطوير.
- تعرفنا على طرق الاستيراد المختلفة:
import module
,from module import item
, وimport module as alias
. - تعلمنا كيفية استكشاف الوحدات باستخدام
dir()
وhelp()
. - استكشفنا بعض الوحدات الأساسية مثل
math
للرياضيات، وrandom
للعشوائية، وdatetime
للوقت، وos
/pathlib
لنظام التشغيل.
تمارين تطبيقية مع الحلول
التمرين 1: طرق الاستيراد المختلفة
المطلوب:
اكتب برنامجًا يحسب مساحة دائرة نصف قطرها 7
. قم بحل المسألة مرتين:
- المرة الأولى: استخدم
import math
للوصول إلىmath.pi
. - المرة الثانية: استخدم
from math import pi
للوصول إلىpi
مباشرة. المعادلة: $Area = \pi \times r^2$
الحل:
# --- الحل للتمرين 1 ---
# --- الطريقة الأولى: import math ---
print("--- باستخدام 'import math' ---")
import math
radius1 = 7
area1 = math.pi * (radius1 ** 2)
print(f"مساحة الدائرة هي: {area1:.2f}")
# --- الطريقة الثانية: from math import pi ---
print("\n--- باستخدام 'from math import pi' ---")
from math import pi
radius2 = 7
area2 = pi * (radius2 ** 2)
print(f"مساحة الدائرة هي: {area2:.2f}")
التمرين 2: حاسبة توزيع الطلاء
المطلوب:
اكتب برنامجًا يسأل المستخدم عن مساحة الجدار بالمتر المربع وعن مساحة التغطية لعلبة طلاء واحدة. يجب على البرنامج حساب وطباعة عدد علب الطلاء التي يحتاجها. استخدم math.ceil()
لتقريب العدد لأعلى دائمًا، لأنه لا يمكنك شراء جزء من علبة.
الحل:
# --- الحل للتمرين 2 ---
import math
print("--- حاسبة علب الطلاء ---")
wall_area_str = input("أدخل مساحة الجدار بالمتر المربع: ")
can_coverage_str = input("كم متر مربع تغطي علبة الطلاء الواحدة؟ ")
wall_area = float(wall_area_str)
can_coverage = float(can_coverage_str)
# حساب العدد المطلوب من العلب (قد يكون عشريًا)
required_cans_float = wall_area / can_coverage
# تقريب العدد لأعلى للحصول على عدد صحيح من العلب
required_cans_int = math.ceil(required_cans_float)
print(f"تحتاج إلى {required_cans_int} علب طلاء لتغطية الجدار بالكامل.")
التمرين 3: مولد الأعذار العشوائي
المطلوب: أنشئ برنامجًا يساعدك على توليد أعذار لعدم القيام بالواجب. أنشئ ثلاث قوائم:
- قائمة بالفاعلين (e.g., “كلبي”, “جاري”, “كائن فضائي”).
- قائمة بالأفعال (e.g., “أكل”, “أخفى”, “أحرق”).
- قائمة بالمفعول به (e.g., “واجبي”, “حاسوبي”, “كتابي”).
استخدم random.choice()
لاختيار عنصر عشوائي من كل قائمة، ثم ادمجها لتكوين جملة عذر مضحكة.
الحل:
# --- الحل للتمرين 3 ---
import random
# 1. تعريف القوائم
subjects = ["كلبي", "جاري", "كائن فضائي", "أخي الصغير"]
verbs = ["أكل", "أخفى", "أحرق", "باع"]
objects = ["واجبي المدرسي", "حاسوبي المحمول", "كتاب الرياضيات"]
# 2. اختيار عنصر عشوائي من كل قائمة
random_subject = random.choice(subjects)
random_verb = random.choice(verbs)
random_object = random.choice(objects)
# 3. تكوين وطباعة العذر
excuse = f"{random_subject} {random_verb} {random_object}!"
print("عذري لليوم هو:")
print(excuse)
التمرين 4: خلط فريق عشوائي
المطلوب:
لديك قائمة بأسماء لاعبين. اكتب برنامجًا يقوم بخلط ترتيب اللاعبين في القائمة بشكل عشوائي باستخدام random.shuffle()
، ثم يطبع القائمة الجديدة بعد الخلط لإنشاء فرق عشوائية.
الحل:
# --- الحل للتمرين 4 ---
import random
players = ["علي", "بدر", "خالد", "داود", "عمر", "فهد"]
print(f"قائمة اللاعبين الأصلية: {players}")
# خلط القائمة بشكل دائم (in-place)
random.shuffle(players)
print(f"ترتيب الفريق العشوائي الجديد: {players}")
التمرين 5: طباعة التاريخ المنسق
المطلوب: اكتب برنامجًا يحصل على تاريخ اليوم الحالي ثم يطبعه بالصيغة التالية: “اليوم هو [اسم اليوم الكامل], [يوم] [اسم الشهر الكامل] [سنة]”. مثال: “اليوم هو الثلاثاء, 15 يوليو 2025”.
الحل:
# --- الحل للتمرين 5 ---
import datetime as dt
# الحصول على تاريخ اليوم
today = dt.date.today()
# تنسيق التاريخ باستخدام رموز strftime
# %A = اسم اليوم الكامل
# %d = رقم اليوم في الشهر
# %B = اسم الشهر الكامل
# %Y = السنة الكاملة
formatted_date = today.strftime("اليوم هو %A, %d %B %Y")
print(formatted_date)
التمرين 6: حاسبة أيام الحياة
المطلوب:
اكتب برنامجًا يسأل المستخدم عن تاريخ ميلاده (بصيغة YYYY-MM-DD
). يجب على البرنامج حساب عدد الأيام التي عاشها المستخدم منذ تاريخ ميلاده حتى اليوم.
الحل:
# --- الحل للتمرين 6 ---
import datetime as dt
# 1. سؤال المستخدم عن تاريخ ميلاده
birthdate_str = input("أدخل تاريخ ميلادك (بصيغة YYYY-MM-DD): ")
# 2. تحويل النص إلى كائن تاريخ
# strptime هو عكس strftime، فهو يحلل النص إلى كائن تاريخ
birthdate_obj = dt.datetime.strptime(birthdate_str, "%Y-%m-%d").date()
# 3. الحصول على تاريخ اليوم
today_date = dt.date.today()
# 4. حساب الفرق بين التاريخين
time_difference = today_date - birthdate_obj
# 5. طباعة عدد الأيام من كائن الفرق الزمني
print(f"لقد عشت ما يقارب {time_difference.days} يومًا. يا له من إنجاز!")
التمرين 7: إنشاء مجلد للمشروع
المطلوب:
اكتب برنامجًا يسأل المستخدم عن اسم مشروع جديد. يجب على البرنامج إنشاء مجلد جديد بهذا الاسم داخل مجلد العمل الحالي. استخدم وحدة os
.
الحل:
# --- الحل للتمرين 7 ---
import os
# 1. سؤال المستخدم عن اسم المجلد
project_name = input("أدخل اسم مجلد المشروع الجديد: ")
# 2. التحقق مما إذا كان المجلد موجودًا بالفعل لتجنب الخطأ
if not os.path.exists(project_name):
# 3. إنشاء المجلد إذا لم يكن موجودًا
os.mkdir(project_name)
print(f"تم إنشاء المجلد '{project_name}' بنجاح.")
else:
print(f"المجلد '{project_name}' موجود بالفعل.")
التمرين 8: مولد كلمة مرور بسيطة
المطلوب: اكتب برنامجًا يولد كلمة مرور عشوائية بسيطة.
- أنشئ قائمة تحتوي على أحرف وأرقام.
- اطلب من المستخدم تحديد طول كلمة المرور.
- استخدم حلقة
for
ودالةrandom.choice()
لاختيار أحرف عشوائية من القائمة وتكوين كلمة المرور.
الحل:
# --- الحل للتمرين 8 ---
import random
# 1. تعريف الأحرف المتاحة
# يمكنك إضافة رموز وأحرف كبيرة لجعلها أقوى
characters = "abcdefghijklmnopqrstuvwxyz0123456789"
# 2. سؤال المستخدم عن الطول
password_length = int(input("أدخل طول كلمة المرور المطلوبة: "))
# 3. توليد كلمة المرور
password = ""
for i in range(password_length):
random_char = random.choice(characters)
password += random_char # إضافة الحرف العشوائي لكلمة المرور
print(f"كلمة المرور المولدة هي: {password}")
التمرين 9: حاسبة مساحة المثلث
المطلوب: اكتب برنامجًا يحسب مساحة المثلث باستخدام صيغة هيرون.
- اطلب من المستخدم إدخال أطوال الأضلاع الثلاثة للمثلث (a, b, c).
- احسب نصف المحيط (s): $s = (a + b + c) / 2$.
- احسب المساحة (Area): $Area = \sqrt{s \times (s-a) \times (s-b) \times (s-c)}$.
استخدم دالة
math.sqrt()
لحساب الجذر التربيعي.
الحل:
# --- الحل للتمرين 9 ---
import math
print("--- حاسبة مساحة المثلث (صيغة هيرون) ---")
a = float(input("أدخل طول الضلع الأول (a): "))
b = float(input("أدخل طول الضلع الثاني (b): "))
c = float(input("أدخل طول الضلع الثالث (c): "))
# 2. حساب نصف المحيط (s)
s = (a + b + c) / 2
# 3. حساب المساحة
# نضع العملية داخل math.sqrt()
area = math.sqrt(s * (s - a) * (s - b) * (s - c))
print(f"مساحة المثلث هي: {area:.2f}")
التمرين 10: سجل الأحداث مع pathlib
المطلوب:
اكتب برنامجًا يقوم بإنشاء ملف سجل events.log
داخل مجلد فرعي اسمه logs
. إذا لم يكن مجلد logs
موجودًا، يجب على البرنامج إنشاؤه أولاً. يجب أن يكتب البرنامج سطرًا واحدًا في الملف يفيد “تم تشغيل النظام” مع التاريخ والوقت الحاليين. استخدم وحدة pathlib
الحديثة.
الحل:
# --- الحل للتمرين 10 ---
from pathlib import Path
import datetime as dt
# 1. إنشاء كائن مسار للمجلد الفرعي 'logs'
log_directory = Path("logs")
# 2. إنشاء المجلد إذا لم يكن موجودًا
# exist_ok=True تمنع حدوث خطأ إذا كان المجلد موجودًا بالفعل
log_directory.mkdir(exist_ok=True)
# 3. إنشاء المسار الكامل للملف
log_file_path = log_directory / "events.log"
# 4. تجهيز رسالة السجل
timestamp = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_message = f"[{timestamp}] - تم تشغيل النظام.\n"
# 5. فتح الملف في وضع الإضافة والكتابة فيه
with open(log_file_path, "a", encoding="utf-8") as file:
file.write(log_message)
print(f"تم تحديث السجل بنجاح في المسار: {log_file_path}")
ماذا بعد؟
رغم قوة المكتبة القياسية، إلا أن القوة الحقيقية لمجتمع بايثون تكمن في آلاف المكتبات الخارجية التي طورها المبرمجون حول العالم. في الفصل الثاني عشر، سنتعلم كيفية تثبيت هذه المكتبات الخارجية واستخدامها لبناء تطبيقات أكثر قوة وتخصصًا.