الانتقال إلى المحتوى

أساسيات البرمجة

علوم الحاسوب الجامعية · الموضوع 1

1.1

ما هو هذا المقرر، وكيفية استخدامه

هذا هو الكورس الأول في علوم الحاسب الجامعية: أساسيات البرمجة , مُدرَّس باستخدام بايثون 3. يفترض عدم وجود خبرة سابقة في البرمجة. كل برنامج في هذه المذكرة مكتمل وقابل للتشغيل — اكتبه، شغّله، غيّر سطرًا واحدًا، وتنبأ بماذا سيحدث قبل التشغيل مجددًا. حلقة التنبؤ ثم التشغيل هي المهارة بأكملها.

الكورس عبارة عن سلم:

  • الوحدات 1.1 إلى 1.3 تبني الآليات: القيم والأنواع، الاختيار، التكرار.
  • الوحدة 1.4 تُعبئ العمل داخل دوال.
  • الوحدات 1.5 و1.6 تضيف المجموعات القياسية والملفات مع معالجة الأخطاء.
  • الوحدة 1.7 هي الانضباط الأعلى: تحليل المشكلات، الاختبار، تصحيح الأخطاء.

كيف تقرأ كل وحدة: قصة قصيرة تقول لماذا هي مهمة؛ صورة أو قاعدة إرشادية تأتي قبل أي بناء نحوي؛ ثم القواعد الدقيقة؛ ثم أمثلة محلولة تتصاعد صعوبة, كل منها يتبعها تتبع يمكنك التحقق منه بتشغيل الكود؛ ثم الأخطاء التي يرتكبها الناس فعليًا؛ ثم ملخص من ثلاثة أسطر. كل مثال هنا يمكن التحقق منه بطريقة ثانية — تشغيلها. قراءة الكود دون تشغيله تشبه قراءة النوتة الموسيقية بدون سماعها.

1.1

القيم والأنواع والإدخال/الإخراج

تُظهر تطبيق التسوق "4.20" — هل هذا نص أم رقم؟ إذا كان نصاً، فإن جمع سعرين يعطي "4.203.50"؛ إذا كان رقماً، فيعطي 8.7. ما يحدث يعتمد على النوع، والوحدة بأكملها 1.1 تتعلم رؤية الأنواع قبل تشغيل أي شيء. الأسماء هي علامات على صناديق؛ التعبيرات تقرأ الصناديق وتنتج صناديق جديدة

قراءة التعبير هي "افتح الصناديق، احسب، أغلق صندوقاً جديداً": int أرقام)، float (عشرية)، str (نص)، bool (True/False). الدالة type(...) تحدد نوع أي قيمة — يمكنك استدعاؤها بحرية أثناء التعلم.

age = 21              # int
price = 4.20          # float
name = "Ada"          # str
open_ = True          # bool
print(type(age))      # <class 'int'>

المتغيرات هي أسماء مرتبطة بقيم؛ التعيين age = 22 يعيد ربط الاسم — الأسماء هي ملصقات على صناديق؛ التعبيرات تقرأ الصناديق وتنتج صناديق جديدة

حالة البرنامج كمربعات: كل علامة اسم تشير إلى مربع قيمتها الخاص؛ إعادة الربط تحرك العلامة، ولا تعدل المربع أبدًا. التعبير 6 * 3.50 يقرأ مربعين وينتج مربع float جديد 21.0
الأسماء هي علامات على صناديق؛ التعبيرات تقرأ الصناديق وتنتج صناديق جديدة

قراءة التعبير تعني "افتح الصناديق، احسب، أغلق صندوقًا جديدًا": count * 3.50 ترقية count = 6 — النتيجة هي int 6، ولا تكون أبداً float 3.50. القاعدة تعزز int — النتيجة هي float 21.0، وليس int 21.

التحويل صريح: int("21") هو 21، لكن "4" + 2 هو TypeError — بايثون يرفض تخمين ما إذا كنت تقصد "42" أو 6. أخرج بـ print(...)؛ أدخل بـ input(...)، الذي يُرجع دائمًا نصًا، لذا يجب تحويل الأرقام:

born = int(input("Birth year? "))
print("About", 2026 - born, "years old")

مثال محلول 1 (كاشير المقهى). count = int(input("Coffees? "))، ثم print("Total:", count * 3.50). عند 6 قهوة يطبع هذا Total: 21.0 — وهو .0 يحدد نوع العائم، لأن int * float يُترقى إلى عائم. مراقبة النوع الخارج من التعبير هو عادة 1.1 الكاملة. تتبعها بالحالة: input يعيد النص "6"؛ int(...) يفتح صندوقًا جديدًا يحتوي على int 6؛ عملية الضرب تُنشئ صندوقًا جديدًا لـ float 21.0؛ print يعرضه.

مثال محلول 2 (الحادث الكلاسيكي، المصلح). يجمع مطبوع لافتات عددًا على رسالة:

count = int(input("Tickets? "))
print("Sold " + count + " today")

قم بتشغيله وترفع Python TypeError: can only concatenate str (not "int") to str — القاعدة ترفض التخمين. الإصلاح يسمي التحويل صراحةً: print("Sold " + str(count) + " today")، أو الأسهل print("Sold", count, "today"), which inserts the spaces for you. The lesson to carry: + يعني الجمع للأرقام، والدمج للنصوص، ولا خلط صامت أبدًا.

أخطاء شائعة. نسيان أن input() تُعطي دائمًا نصًا، لذا input() * 2 تكرار النص بدلاً من مضاعفة رقم. كتابة 4.20 + 6 و توقع إجابة int — أي عائم في التعبير يُنتج عائمًا. الثقة في 0.1 + 0.2 == 0.3 (إنها False؛ التقريب الثنائي — يُظهر 1.2 الإصلاح).

ملخص: أربعة أنواع أساسية تحدد كل عملية؛ الأسماء وسوم، والتعيين يعيد الربط؛ التعبيرات تخلط الأنواع بالترقية مع العوادم؛ التحويلات صريحة و input() تحتاج واحدة.

مفردات تدريب
English العربية
programming fundamentals/ˈprəʊɡræmɪŋ ˌfʌndəˈmentlz/ أساسيات البرمجة
type/taɪp/ نوع
set/set/ مجموعة
1.2

الاختيار: بين المسارات

يجب أن يفرض بوابة الحديقة الترفيهية رسومًا مختلفة للأطفال والكبار وكبار السن — برنامج واحد، مسارات متعددة. الاختيار هو كيفية اختيار البرنامج: if، elif، العمر else، طالب: الفرع الحقيقي الأول يحدد السعر

مخطط تدفق لقواعد أسعار السينما مع التحقق من العمر قبل التحقق من الطالب؛ طالب عمره 70 سنة يأخذ الفرع الحقيقي الأول ويدفع 5
العمر 70، طالب: الفرع الأول الصحيح يحدد السعر

الشروط هي أي تعبير منطقي؛ المقارنات (==، !=، <، >=) والـ logic (and, or, not) build it. Two rules make every decision readable:

  1. الفروع تُختبر من الأعلى إلى الأسفل؛ الفعل الأول الصحيح هو الفائز والباقي يتم تجاهلهم.
  2. المسافة البادئة ليست زينة — بل هي كتلة الكود. مسافة واحدة إضافية تغير الخطوط التي تنتمي إلى الفرع.
temp = 37.5
if temp >= 38:
    print("Fever")
elif temp >= 36 and temp < 38:
    print("Normal")
else:
    print("Low")

مثال محلول 1 (أسعار السينما). تحت 12 أو 65+، يُدفع 5، أما الطلاب فيدفعون 7، مثال محلول 10 (فئات الدرجات، متصاعدة). نفس الهيكل الأساسي، الآن مع سلسلة

age = int(input("Age? "))
student = input("Student? y/n ") == "y"
if age < 12 or age >= 65:
    price = 5
elif student:
    price = 7
else:
    price = 10
print("Pay", price)

التسلسل مهم: الفرع الأول الصحيح هو الذي يُلعب، ولهذا السبب يسبق التحقق من العمر تحقق الطلاب — طالب عمره 70 سنة يجب أن يدفع 5، وهذا الترتيب يؤكد ذلك. شغّل المثال بـ 70 و y لترى المسار الأيسر للمخطط الانسيابي.

مثال محلول 2 (فئات الدرجات، متصاعد). نفس الهيكل الأساسي، الآن مع سلسلة حيث يحتاج كل elif إلى مقارنة واحدة فقط، لأن الاختبارات التي فوقها قد فشلت بالفعل:

score = int(input("Score? "))
if score >= 80:
    band = "A"
elif score >= 70:
    band = "B"
elif score >= 60:
    band = "C"
else:
    band = "F"
print("Band:", band)

عند 79 يفشل الاختبار الأول وينجح الثاني: Band: B. التصاعد إلى ملاحظة: لا يحتاج elif score >= 70 أيضًا إلى and score < 80 — الوصول إلى ذلك السطر يُثبت بالفعل أن النتيجة أقل من 80. الاعتماد على هذا الاندفاع هو ما يجعل السلاسل قصيرة؛ إعادة اختبار كل شيء هي الطريقة الأطول والأكثر خطأً للمبتدئين النسخة.

تتطلب المقارنات ذات الفاصلة العائمة حذرًا: 0.1 + 0.2 == 0.3 هي False (الترميز الثنائي التقريب)، لذا قارن مع هامش خطأ: abs(x - y) < 1e-9.

أخطاء شائعة. كتابة = بدلاً من == — وهو الخطأ الكلاسيكي، وPython ملخص: الشروط تختار المسارات، الأولى التي تحقق الشرط تكتسب، والمحاذاة هي كتلة الكود؛ ترتيب الاختبارات من المحدد إلى العام؛ مقاربات الأعداد العائمة تتم عبر هامش خطأ، ولا تستخدم SyntaxError. الحالة الخاصة بعد الحالة العامة، لذلك تفوز العامة دائمًا. استخدام دفع فواتير elif يدوياً هو مهنة؛ باستخدام حلقة تكرار، هو برنامج. التكرار تم اكتشافه.

شرط ما يتحقق. السؤال التصميمي دائماً: هل تعرف عدد الرحلات، أم أن شرطاً يقرر؟ اختبارات محددة ثم عامة؛ تقارن الأعداد العشرية بحدود tolerances، ولا تقارن أبدًا بـ ==.

1.3

التكرار: القيام بذلك مرة أخرى

دفع فواتير 5,000 يدويًا هو مهنة؛ باستخدام حلقة تكرار، يكون برنامجًا. التكرار يعيد العمل: حلقة for تمر على سلسلة معروفة؛ حلقة while تعمل طالما أن شرط متحقق. السؤال التصميمي دائمًا: هل تعرف عدد الرحلات، أم أن شرط يقرر؟

total = 0
for i in range(1, 101):      # 1..100 — range stops BEFORE its end
    total += i
print(total)                  # 5050

استخدم for عندما يكون عدد الرحلات معروفًا؛ استخدم while عندما يقرر شرط ما. كل while تحتاج ثلاثة أشياء مرئية في الكود: بداية المتغير، والشرط، وشيء داخله يقترب من الخروج — وإلا فهي حلقة تكرار لا نهائية حلقة**.

حلقة while المضروب بجانب جدول التتبع: n وfactorial بعد كل جولة، من 5 و1 إلى 1 و120، عندما يصبح الشرط False
جدتتبع لحلقة المضروب
n = 5
factorial = 1
while n > 1:
    factorial *= n
    n -= 1                    # the step toward exiting
print(factorial)              # 120

جدالتتبع هو عادة التحقق في المساق للحلقات: تابع المتغيرات جولةً بجولة، على الورق أولاً. بالنسبة لحلقة المضروب: (n=5, f=1) → (4, 5) → (3, 20) → (2, 60) → (1, 120). قم بإنشاء الجدول يدوياً، ثم أضف print(n, factorial) داخل الحلقة واترك بايثون يصحح لك.

مثال محلول 2 (بحث مع break، متصاعد). أوجد أول مضاعف لـ 7 الذي يكون أكبر من 100 — عدد الرحلات غير معروف، الشرط يحدد:

n = 100
while True:
    if n % 7 == 0:
        break                 # found it — leave the loop now
    n += 1
print(n)                      # 105

التتبع قصير: 100، 101، …، 104 تفشل جميعها الاختبار؛ 105 تنجح وbreak يخرج. break يغادر الحلقة مبكراً؛ continue يقفز إلى الجولة التالية. كلاهما أدوات للوضوح — حلقة يجب أن تبحث حتى تجد شيئاً، ثم تتوقف، تكون أكثر وضوحاً مع break. التصاعد التالي، مضاعفة المال: عند 5% سنوياً، كم تستغرق 1000 لتصل إلى 2000؟

balance = 1000.0
years = 0
while balance < 2000.0:       # the condition itself is the goal
    balance *= 1.05
    years += 1
print(years, round(balance, 2))   # 15 2078.93

خمسة عشر عاماً، وتتوقف الحلقة لحظة انعكاس الشرط — جدالتتبع سيظهر الرصيد يتجاوز الخط عند 2078.93، وليس الوصول بدقة إلى 2000.

أخطاء شائعة. تعديل القائمة (الوحدة 1.5) أو متغير الحلقة الذي أنت for-تكرره. range(1, 100) عندما كان المقصود 100 — النهاية مستبعدة. while whose exit step is missing or commented out: the condition never flips, وتتجمد البرنامج.

ملخص: for لأعداد الرحلات المعروفة، while للشروط؛ كل حلقة تظهر البداية، الشرط والخطوة؛ التتبع على الورق، ثم الطباعة بجودة break وcontinue من أجل المخارج النظيفة المبكرة.

1.4

الدوال: تسمية مهمة مرة واحدة

يظهر نفس حساب السعر في خمسة أماكن؛ تتغير قاعدة الضريبة؛ أربعة من الخمس يتم تحديثها. الدالة تُجمّع مهمة خلف اسم لتُكتب مرة واحدة وتُثقى بها في كل مكان: المعاملات الداخل، قيمة الإرجاع الخارج. def يعرّف؛ الاستدعاء يُنفّذ.

def total_price(count, unit=3.50):
    """Return the total for count items at unit price."""
    return count * unit

print(total_price(6))            # 21.0
print(total_price(6, unit=4.0))  # 24.0

يعطي التعريف معاملاً (count، unit)؛ يزوّد الاستدعاء بـ حجة (6). القيمة الافتراضية (unit=3.50) تجعل الحجة اختيارية. return تعيد قيمة وتنهى الاستدعاء؛ الطباعة ليست إرجاعاً — دالة بدون return تُرجع None، والمكلم الذي يحاول إجراء عمليات حسابية عليها يحصل على TypeError.

إطارات استدعاء ثلاثة: استدعاء print calls order_total(250, 4)، والذي يتوقف أثناء تشغيل add_fee(1000)؛ 1003 يُعاد عبر السلسلة كل استدعاء يحصل على نطاق محلي خاص به: الأسماء داخله غير مرئية

خارجه، وتختفي عند انتهاء الاستدعاء. تتتبع الاستدعاءات المتداخلة يقرأ: المُجاري يتوقف ← المنفّذ يُنفّذ ← قيمة الإرجاع تستقر في المُجاري. المتصل يتوقف ← الدالة المُستدعاة تعمل ← قيمة الإرجاع تستقر في المتصل.

مثال محلول 1 (الطلب شمل الرسوم).

def add_fee(amount):
    """Return amount plus a fixed 3 pence fee."""
    return amount + 3

def order_total(unit_pence, quantity):
    """Return the order total: subtotal plus the fixed fee."""
    return add_fee(unit_pence * quantity)

print(order_total(250, 4))   # 1003

العقد في نص التوثيق مهم: بنص كامل داخل، بنص كامل خارج. تتبع order_total(250, 4): المجموع الفرعي 1000، add_fee يُعيد 1003 — وإطار يُظهر المخطط أعلاه التوقف والتسليم.

مثال محلول 2 (خوارزمية حقيقية داخل دالة صغيرة، مُصعَّبة). يعيد is_prime(n) True عندما لا يقسم أي عنصر من 2 إلى $\sqrt{n}$ الرقم n:

def is_prime(n):
    if n < 2:
        return False
    d = 2
    while d * d <= n:        # only test up to the square root
        if n % d == 0:
            return False     # found a divisor — answer known, stop
        d += 1
    return True

print([p for p in range(2, 30) if is_prime(p)])
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

تلتقي هنا عادتان في الدوال: إرجاع مبكر return يُنهِي الاستدعاء فور knowing الإجابة (لا حاجة لمتغير علم)، والحد العلوي للحلقة d * d <= n مستمد من التفريغ — إذا كان $n = a \times b$ مع $a \le b$، فإن $a \le \sqrt{n}$، لذا فإن اختبار ما وراء $\sqrt{n}$ يعيد اختبار قواسم تم رؤيتها سابقاً. شغّل الكود: القائمة ستكون تماماً الأعداد الأولية الأصغر من 30.

أخطاء شائعة. الطباعة داخل الدالة بدلاً من الإرجاع، مما يجعل النتيجة غير قابلة لإعادة الاستخدام. نسيان الـ return في أحد المسارات — ذلك المسار يُنتج صامتاً None. الوصول إلى المتغيرات المحلية للدالة من الخارج؛ فهي تزول عند انتهاء الاستدعاء.

ملخص: def مرة واحدة، استدعاء من أي مكان؛ المعاملات تدخل، قيمة واحدة تخرج عبر return؛ الإرجاعات المبكرة تُنهي الاستدعاء؛ المتغيرات المحلية تظهر وتختفي مع الاستدعاء؛ وثائق الوصف تحدد العقد.

1.5

المجموعات: القوائم، القواميس، الأزواج المرتبة، المجموعات

تحتاج كاشير المقهى إلى طلبات اليوم مرتبة، والقائمة حسب الاسم، وموقعاً لا يجب أن يتغير، ومشروبات يومية فريدة. أربع مهام، أربعة حاويات — الاختيار بينها هو قرار التصميم في الوحدة 1.5.

القائمة هي تسلسل مرتب وقابل للتعديل: marks = [72, 85, 61]، مُرقَّمة من 0، ومقطوعة باستخدام marks[1:3]. القاموس يربط المفاتيح بالقيم: price = {"flat white": 3.5, "tea": 2.8}، تُقرأ وتُكتب بواسطة مفتاح. الزوجة هي تسلسل ثابت (53.1, -1.5) — مناسبة للإحداثيات التي لا ينبغي تغييرها. الـ مجموعة تحتوي على عناصر فريدة دون ترتيب: {"a", "b"}.

marks = [72, 85, 61]
marks.append(90)               # [72, 85, 61, 90]
best = max(marks)              # 90
average = sum(marks) / len(marks)   # 77.0
يُشير كل من a و b إلى نفس كائن القائمة، الذي يحتوي على 1 و 2 بعد b.append(2)
الاقتباس: اسمان، قائمة واحدة

التعيين لا ينسخ أبداً: a = [1]; b = a; b.append(2) يجعل a [1, 2] — القائمة مشتركة، الأسماء ليست كذلك. هذا الاقتباس يعيد تجميع صناديق 1.1 مرة أخرى، الآن بوسمين على صندوق واحد، ويشرح القاعدة التالية أيضاً: عند تعديل قائمة أثناء looping over it skips elements — loop over a copy (for m in marks[:]) or build a قائمة جديدة.

مثال محلول 1 (عدّ حسب الفئة).

orders = ["tea", "flat white", "tea", "tea", "mocha"]
tally = {}
for item in orders:
    tally[item] = tally.get(item, 0) + 1
print(tally)   # {'tea': 3, 'flat white': 1, 'mocha': 1}

مفتاح القاموس .get(key, 0) يوفر 0 للمشهد الأول — الصيغة التي يجعل العد سطرًا واحداً. تحقق يدوياً: "tea" تظهر ثلاث مرات في orders، والعداد المطبوع يؤكد ذلك.

مثال محلول 2 (الأكثر مبيعاً في اليوم، متدرج). استناداً إلى العدّ، أفرد العنصر الأعلى وعدده:

best = max(tally, key=tally.get)
print(best, tally[best])       # tea 3

يعتمد المعامل key=tally.get على طلب max لمقارنة العناصر حسب عددها بدلاً من الترتيب الأبجدي — نفس حيل key= لترتيب أي مجموعة بأي معيار. أهمية التدرج تكمن في أن البرامج الحقيقية تربط هذه الأدوات معاً (العد ثم الترتيب) بدلاً من إعادة فحص orders مرتين.

اختيار المجموعة هو قرار التصميم: الطلب + التكرار → قائمة؛ البحث بالاسم → قاموس؛ تجميع ثابت → زوج مرتب؛ التميز → مجموعة. الاسم ← قاموس؛ التجميع الثابت ← زوج مرتب؛ التفرد ← مجموعة.

افتراض أن tally[item] += 1 ينسخ قائمة؛ بل إنه يُشير إليها. (KeyError) — .get هو الحل. توقع أن المجموعة أو القاموس يحفظ الترتيب. بافتراض أن b = a ينسخ قائمة؛ فهو يشار إليها برفق.

ملخص: أربعة حاويات لأربع مهام؛ التعديل يشارك، ولا ينسخ أبدًا؛ .get كتلة key= هي الحاجز الآمن: مهما حدث داخلها، تُغلق الملف.

مفردات تدريب
English العربية
aliasing/ˈeɪlɪəsɪŋ/ استخدام اسم مستعار
1.6

الملفات والأخطاء

تُغلق المقهى، تنقطع الكهرباء — وينجو حصيلة الصباح فقط إذا كان البرنامج قد كتبه إلى القرص. الملف يدوم أطول من البرنامج. with open(path) as f: opens, closes on exit, and reads text; open(path, "w") يكتب (ويفرغه أولاً — الحادثة الكلاسيكية).

with open("log.txt", "w") as f:
    f.write("opened\n")

with open("log.txt") as f:
    for line in f:
        print(line.rstrip())     # rstrip removes the trailing newline

حقل with هو سكة الأمان: أي حدث داخله، يُغلق الملف. القراءة تعطي الأسطر مع أسطر جديدة، لذا .rstrip() يقع في كل حلقة.

الأخطاء هي قيم ترفعها Python كـ استثناءات: FileNotFoundError, ValueError، KeyError، TypeError. try/except يلتقط نوعًا مسمى — ولا يلتقط أبدًا except: عارية تُخفي الأخطاء الحقيقية.

مثال محلول 1 (ملف الإعدادات المفقود). قراءة حجم نص من ملف إعدادات قد يكون مفقودًا، أو قد لا يحتوي على عدد صحيح:

try:
    with open("settings.txt") as f:
        size = int(f.read().strip())
except FileNotFoundError:
    size = 12                    # no file yet: a sensible default
except ValueError:
    size = 12                    # the file holds "big", not a number
print("Text size", size)

شغّله ثلاث مرات — بوضع 16 في الملف، وبدون ملف، وبوضع big في الملف — وسيقوم بطباعة حجم قابل للاستخدام في كل مرة، عبر ثلاث مسارات مختلفة. هذا هو جوهر الكود المتين: تحديد مسار واحد معقول التعامل مع الخطأ المتوقع، حيث يمكنك الاستجابة له؛ اترك الباقي ينهار بصوت عالٍ. له؛ ودع البقية تنهار بصخب.

قارئ الإعدادات: كتلة try تفتح وتقرأ وتحول القيمة؛ إما أن تنجح، أو أن يُفعّل فرع FileNotFoundError أو ValueError الحجم الافتراضي 12؛ تتلاقى جميع المسارات الثلاثة ويواصل البرنامج عمله

مثال محلول 2 (حلقة إدخال متينة، متصاعدة). استمر في الطلب حتى يقوم المستخدم بإدخال عدد صحيح:

def read_count():
    while True:
        try:
            return int(input("How many? "))
        except ValueError:
            print("Whole numbers only.")

print(read_count())

عقد الدالة (x) والاستثناء (4) — وهو جوهر التطوير. يطلب while True مجددًا؛ تنجح الجولة الثانية في int(...) ويخرج return نسيان 1.3، بحيث تظهر الأسطر مزدوجة التباعد في المخرجات. ملخص: 1.4 للقراءة والكتابة معًا؛ 1.6 يفرغ أولاً؛ الاستثناءات هي قيم — التقاط النوع المسمي المتوقع، وافتقر بعقلانية، واترك الباقي ينهار. التصاعد.

أخطاء شائعة. open(path, "w") في المسار الخاطئ: يتم إنشاء الملف أو إفراغه قبل أن تلاحظ. emptied before you notice. Catching Exception broadly and continuing with broken state. Forgetting .rstrip(), so output shows double-spaced lines.

ملخص: استخدام with open(...) للقراءة والكتابة؛ استخدام "w" لتفريغ الملف أولاً؛ الاستثناءات هي قيم — التقط النوع المسمى الذي تتوقعه، واستعد بشكل معقول، ودع البقية تنهار.

مفردات تدريب
English العربية
value/ˈvæljuː/ قيمة
variables/ˈveərɪəblz/ المتغيرات
string/strɪŋ/ سلسلة نصية
selection/sɪˈlekʃn/ اختيار
iteration/ˌɪtəˈreɪʃn/ التكرار
infinite loop/ˈɪnfɪnət luːp/ حلقة لا نهائية
trace table/treɪs ˈteɪbl/ جدول التتبع
function/ˈfʌŋkʃn/ دالة
return value/rɪˈtɜːn ˈvæljuː/ القيمة المرتجعة
parameter/pəˈræmɪtə/ المعاملات
argument/ˈɑːɡjuːmənt/ حُجْجة
local scope/ˈləʊkl skəʊp/ نطاق محلي
list/lɪst/ قائمة
dictionary/ˈdɪkʃənəri/ مفردات
tuple/ˈtuːpl/ زوجة
file/faɪl/ ملف
exceptions استثناءات
decomposition/ˌdiːkɒmpəˈzɪʃn/ تحليل
testing/ˈtestɪŋ/ اختبار
debugging/ˈdiːbʌɡɪŋ/ تصحيح أخطاء
1.7

التحليل، الاختبار، وتصحيح الأخطاء

فريقان يكتبان نفس التطبيق؛ أحدهما يُسلمه خلال أسبوع، والآخر يغرق في العمل لمدة شهر. الفرق ليس سرعة الكتابة — بل أن كود الفريق السريع مبني من أجزاء صغيرة يمكن إثبات صحتها لكل جزء على حدة، بينما يقوم الفريق البطيء بتصحيح أخطاء تطبيق كامل دفعة واحدة. difference is not typing speed — it is that the fast team's code is built from small القيم — مثل البطاريات والمستشعرات ومصادر المنطق وشبكات الانحياز داخل كل مكبر صوتي. الوحدة 1.7 هي تلك التخصص.

التجزئة تُقسّم المشكلة إلى وظائف لكل منها مهمة واحدة — كل صغيرة بشكل كافٍ لاختبارها بشكل مستقل. الاختبار يقارن المخرجات الفعلية للوظيفة مع المُتوقعة، عند الحدود: الصفر، واحد، فارغ، سالب، ضخم.

حلقة الاختبار الدافع: اكتب اختباراً يفشل يُحدد العقد؛ شغله ولاحظ فشله للسبب الصحيح؛ اكتب أبسط جسم ممكن ينجح؛ أعد التشغيل حتى يصبح أخضر؛ أعد الهيكلة بينما تحافظ الاختبارات على الشكل
حلقة الاختبار الدافع: أحمر، أخضر، إعادة هيكلة
def add_fee(amount):
    return amount + 3

def order_total(unit_pence, quantity):
    return add_fee(unit_pence * quantity)

assert order_total(250, 4) == 1003
assert order_total(250, 0) == 3      # the zero-quantity boundary
assert order_total(0, 4) == 3

إن assert لا يُشعل أبداً هو اختبار ناجح. اكتب الاختبارات قبل كتابة الجسم إن أمكن — فهي العقد القابلة للتنفيذ، والحلقة أعلاه (أحمر ← أخضر ← إعادة هيكلة) هي هذه العادة التي تعمل باستمرار.

مثال محلول 1 (توسيع الاختبارات مع الوظيفة). قم بتوسيع order_total بخصم 10% على مبلغ £10 — حيث يُكتب الاختبار أولاً عند الحد الجديد:

def order_total(unit_pence, quantity):
    subtotal = add_fee(unit_pence * quantity)
    if subtotal >= 1000:             # pence: over £10
        subtotal = int(subtotal * 0.9)
    return subtotal

assert order_total(200, 4) == 803    # under £10 — unchanged
assert order_total(250, 4) == 902    # 1003 pence → 10% off → 902.7 → 902
assert order_total(250, 5) == 1127   # 1253 pence → 1127.7 → 1127

تحقق من الاختبار الأوسط يدوياً: المجموع الفرعي 1003، وخصم عشر في المئة يعطي 902.7، و int(...) يتم تقريبه للأسفل إلى 902. لاحظ assertion الأول أيضاً: عند 200 بنس وأربع أكواب يبقى الإجمالي 803 — تثبت اختبارات الحدود أن الخصم يُشعل وأنه لا يُشعل مبكراً.

مثال محلول 2 (تقطيع خطأ باستخدام أوامر الطباعة، متصاعد). إحصائيات 1.5 طباعة {'tea': 3} لكن السطر الأكثر مبيعاً يطبع المشروب الخاطئ. الطريقة: (1) إعادة الإنتاج بأصغر مدخل يفشل؛ (2) طباعة القيم عند الحد between the trusted part and the suspected part — here, the tally before the max; (3) إصلاح شيء واحد؛ (4) إعادة تشغيل الاختبارات. نقل أمر الطباعة إلى منتصف الكود كل تشغيل ينصف البحث: أربعة أوامر طباعة تكشف خطأً في برنامج مكون من ستة عشر سطرًا، ومع ذلك فإنه يختبئ.

التصحيح هو تحديد الفارق بين ما تعتقد أن الكود يقوم به وما يقوم به فعليًا — أمر الطباعة عند حدود الثقة/الشك هو الأداة.

أخطاء شائعة. اختبار المسار السعيد فقط: الحدود (الصفر، واحد، فارغ، سالبة) هي حيث تنهار البرامج. كتابة أسبوع من الكود قبل أول اختبار، ثم تصحيح جبال. إصلاح شيئين معًا، بحيث لا يعني أي منهما anything.

ملخص: افكك حتى يختبر كل جزء بمفرده؛ تأكد من الحدود بمجرد وجود دالة اكتب الاختبار أولاً عندما تستطيع؛ صحح باستخدام التقسيم الثنائي بأوامر الطباعة عند حدود الثقة — وهي العادة التي يُبنى عليها الدرجة بأكملها.

دروس تفاعلية حول هذا الموضوع

ا-working عليه خطوة بخطوة، مع تمارين تحقق فوري.

المزيد من المواضيع في علوم الحاسوب الجامعية

تسجيل الدخول أو إنشاء حساب

IGCSE, A-Level & AP