إطلاق الاستثناءات

14.5 إطلاق الاستثناءات

أهداف التعلم

في نهاية هذا القسم، ينبغي أن تكون قادرًا على:

  • استخدام تعليمة raise للإشارة إلى أن إدخال المستخدم غير صالح.
  • شرح سير التنفيذ عند إطلاق استثناء.

تعليمة raise

يمكن للبرنامج إطلاق استثناء عند اكتشاف خطأ. إطلاق استثناء يجبر البرنامج على التعامل مع الخطأ. إذا لم يُعالَج الاستثناء باستخدام try و except، فإن البرنامج يعرض رسالة خطأ ويتوقف.

مثال 14.6

حجم بيتزا غير صالح

يمثل الصنف التالي بيتزا معروضة للبيع. يربط قاموس SIZES اختصارًا باسم الحجم وسعره. يتحقق السطر 11 مما إذا كان الحجم المستلم بواسطة المُنشئ موجودًا في القاموس. يطلق السطر 12 استثناء ValueError مع رسالة خطأ محددة.

1
class Pizza:
2
3
    SIZES = {
4
        "S": ("Small", 5.99),
5
        "M": ("Medium", 7.99),
6
        "L": ("Large", 9.99),
7
        "XL": ("X-Large", 11.99),
8
    }
9
10
    def __init__(self, size):
11
        if size not in Pizza.SIZES:
12
          raise ValueError(f"Unknown size '{size}'")
13
        self.size = size
14
15
    def __str__(self):
16
        name, price = Pizza.SIZES[self.size]
17
        return f"{name} pizza for ${price}"
18
19
if __name__ == "__main__":
20
    p1 = Pizza("L")
21
    print(p1)
22
    p2 = Pizza("Z")
23
    print(p2)
    Large pizza for $9.99
    Traceback (most recent call last):
      File "pizza.py", line 23, in <module>
        p2 = Pizza("Z")
      File "pizza.py", line 12, in __init__
        raise ValueError(f"Unknown size '{size}'")
    ValueError: Unknown size 'Z'

يمنع إطلاق استثناء في مُنشئ من إنشاء كائن غير صالح. في المثال، تم إنشاء p1 ولكن لم يُنشأ p2.

مفاهيم تطبيقية

توقع المخرجات باستخدام raise

لكل مقتطف شِفرة، ما المخرجات؟

1.
p3 = Pizza("M")
print(p3)
  1. Medium pizza for $7.99
  2. ValueError: Unknown size 'M'
  3. TypeError: missing argument
2.
raise PizzaError("Invalid size")
  1. Invalid size
  2. PizzaError: Invalid size
  3. NameError: name 'PizzaError' is not defined
3.
raise ValueError
  1. ValueError
  2. NameError: name 'ValueError' is not defined
  3. SyntaxError: Missing parenthesis in call to 'ValueError'

جرّب بنفسك

كائنات اللغة

يستند ملف top27.csv إلى قائمة ويكيبيديا للغات حسب عدد المتحدثين الأصليين. يرغب عالم لغويات في العمل مع هذه البيانات بطريقة كائنية التوجه (object-oriented) وقد عرَّف بالفعل صنفَ Language. ومع ذلك، لا تعمل الشِفرة بشكل صحيح بسبب الأخطاء في ملف CSV. (لا يمكن تغيير برنامج CSV لأن الغرض من البرنامج هو اكتشاف هذه الأنواع من الأخطاء).

مهمتك هي تعديل المُنشئ لإطلاق استثناء ValueError في الحالات التالية:

  • إذا لم يحتوي السطر على أربع قيم بالضبط (مفصولة بفواصل).
  • إذا لم يكن عدد المتحدثين عددًا عشريًا موجبًا.

ملاحظة: يتضمن ملف top27.csv المقدم أخطاء للغات الإنجليزية والكورية والفرنسية. يجب أن يطلق برنامجك استثناء ValueError لهذه اللغات فقط. لا ينبغي إطلاق أي أخطاء أخرى (بما في ذلك IndexError).

جرّب بنفسك

البحث عن المفاتيح

عند البحث عن قيمة في قاموس، يجب أن يتطابق المفتاح تمامًا. مثال: بالنظر إلى fruit = {"apple": 1, "banana": 2}، فإن التعبير fruit["Apple"] يطلق استثناء KeyError لأن "Apple" تختلف عن "apple". وبالمثل، يطلق fruit["NANA"] استثناء KeyError لأن "nana" لا يتطابق تمامًا مع "banana".

نفّذ الدالّة lookup(). تحاول هذه الدالّة العثور على مفتاح في القاموس يتطابق مع مصطلح البحث. يتطابق المفتاح إذا كان مصطلح البحث جزءًا فرعيًا (substring) من المفتاح، مع تجاهل حالة الأحرف. مثال: المفتاح "banana" يتطابق مع مصطلح البحث "NANA".

إذا لم يتم العثور على مفاتيح متطابقة، يجب أن تطلق lookup() استثناء KeyError مع الرسالة "search term not found". إذا تم العثور على تطابقات متعددة، يجب أن تطلق lookup() استثناء KeyError مع الرسالة "multiple keys found". بخلاف ذلك، يجب أن تُرجع lookup() كلاً من المفتاح والقيمة للعنصر المتطابق في القاموس.

بالنظر إلى ملف books.csv، يجب أن تكون المخرجات كالتالي:

    Found: ('Pride and Prejudice', 9780141439518)
    Found: ('The Hobbit', 9780547928227)
    Error: search term not found
    Error: multiple keys found