استقبال المدخلات من مستخدم البرنامج
قراءة ما يكتبه المستخدم عبر input()، ولماذا تكون المدخلات دائماً نصوصاً str، والأخطاء التي تظهر عند التحويل عبر int() و float().
كيف تريد أن تتعلم؟
المشكلة التي نقوم بحلها
حتى الآن كانت الأرقام في كل برامجنا مكتوبة داخل الملف نفسه. إذا أردت تشغيل البرنامج بأرقام أخرى كان عليك فتح الملف وتعديله.
البرامج الحقيقية لا تعمل بهذه الطريقة. البرنامج يسأل، والمستخدم يجيب.
في بايثون، السؤال هو عمل الدالة (function) input(). تعلّمها يستغرق دقيقة واحدة. لكن تأتي معها قاعدة تُوقع كل مبرمج جديد مرة واحدة على الأقل: ما تعيده input() هو دائماً سلسلة نصية (string) — حتى لو كتب المستخدم رقماً واضحاً. عدم معرفة هذه القاعدة وحدها يكفي لكسر أول برنامج حسابي تكتبه.
في نهاية هذا الفصل ستكون قادراً على
- قراءة ما يكتبه المستخدم عبر
input()، مع عرض سؤال واضح - شرح لماذا يكون الإدخال دائماً من النوع
str - تحويله إلى رقم باستخدام
int()وfloat() - التمييز بين
TypeErrorوValueErrorوالإجابة الخاطئة التي لا يظهر معها أي خطأ - تنظيف الإدخال حتى لا تكسر مسافة زائدة برنامجك
المتطلبات السابقة: التعامل مع النصوص — الفهرسة، التقطيع، ونصوص التنسيق (f-strings).
كيف تعمل input()
name = input("What is your name? ")
print(f"Hello, {name}!")عند التشغيل:
What is your name? Rafi
Hello, Rafi!حدثت ثلاثة أشياء. عرضت input() السؤال الموجود بين القوسين في الطرفية (terminal)؛ ثم توقفت وانتظرت حتى كتب المستخدم شيئاً وضغط Enter؛ ثم أعادت ما كُتب، وحفظناه في name.
لاحظ المسافة في نهاية السؤال — "What is your name? ". بدونها يلتصق ما يكتبه المستخدم بالسؤال ويبدو شكله سيئاً.
يجب تشغيل هذه البرامج في الطرفية. تنتظرinput()أن يكتب أحد شيئاً، لذلك لا تعمل في موقع ويب أو في نافذة المعاينة داخل المحرر. شغّلpython ask.pyفي طرفيتك — وهكذا يسير هذا المقرر دائماً.
القاعدة التي توقع الجميع مرة واحدة
age = input("Your age: ")
print(type(age))
print("Next year:", age + 1)Your age: 22
<class 'str'>
Traceback (most recent call last):
File "D:\python-lab\lesson-07\ask.py", line 3, in <module>
print("Next year:", age + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to strكتب المستخدم 22. الشاشة تُظهر رقماً. لكن type(age) تقول str. (سطر File يحتوي على المسار الكامل لملفك، لذلك سيبدو مختلفاً على حاسوبك.)
السبب بسيط إذا فكرت فيه: لوحة المفاتيح تُنتج أحرفاً، لا أرقاماً. قد يكتب المستخدم 22 أو abc أو 12.5. كان بإمكان input() أن تخمّن — "هذا يبدو رقماً، سأحوّله" — لكن عندها سيعيد السطر نفسه str أحياناً و int أحياناً أخرى، ولن تعرف مسبقاً ما الذي سيأتي. لذلك يلتزم بايثون بقاعدة واحدة: دائماً سلسلة نصية. التحويل مسؤوليتك أنت.
int() و float()
age = input("Your age: ")
age = int(age)
print(type(age))
print("Next year:", age + 1)Your age: 22
<class 'int'>
Next year: 23يمكن كتابة الخطوتين في سطر واحد، وهكذا تُكتب عادة:
age = int(input("Your age: "))
print("Next year:", age + 1)اقرأها من الداخل إلى الخارج: input() جلبت سلسلة نصية، و int() حوّلتها إلى عدد صحيح، ثم وُضعت النتيجة في age.
للأعداد العشرية استخدم float():
price = float(input("Price: "))
print("With tax:", round(price * 1.15, 2))Price: 249.50
With tax: 286.92متى تستخدم أيّهما: int للأشياء التي تُعدّ (الأعمار، الأعداد، الكميات)، و float للأشياء التي تُقاس (الأسعار، الأوزان، المتوسطات).
خطآن، وغلطة لا يظهر معها أي خطأ
عند نسيان التحويل أو وصول إدخال غير صالح، قد يحدث واحد من ثلاثة أشياء مختلفة. من السهل الخلط بين أسمائها، لذلك انظر إليها جنباً إلى جنب.
TypeError — النوع نفسه خاطئ. نسيت التحويل وحاولت جمع رقم مع سلسلة نصية:
qty = input("Quantity: ")
print(qty + 2)Quantity: 3
Traceback (most recent call last):
File "D:\python-lab\lesson-07\ask.py", line 2, in <module>
print(qty + 2)
~~~~^~~
TypeError: can only concatenate str (not "int") to strفي qty توجد السلسلة النصية "3"، والعامل + مع السلاسل النصية لا يضمّ إلا سلسلة نصية أخرى، لا رقماً. بايثون لا يخمّن هل أردت الجمع أم الضم — لذلك يتوقف.
لا خطأ إطلاقاً — مجرد إجابة خاطئة. اكتب الآن * بدلاً من +، وما زال التحويل غائباً:
qty = input("Quantity: ")
print(qty * 2)Quantity: 3
33هذه المرة لم يظهر أي خطأ. "3" * 2 تعني تكرار النص مرتين — "33". اشتغل البرنامج والإجابة خاطئة. الإجابة الخاطئة الصامتة أسوأ من الخطأ، لأن لا شيء يوقفك ليخبرك.
ValueError — النوع صحيح، لكن النص ليس رقماً:
age = int(input("Your age: "))Your age: twenty
Traceback (most recent call last):
File "D:\python-lab\lesson-07\ask.py", line 1, in <module>
age = int(input("Your age: "))
^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'twenty'int() مستعدة للقيام بالعمل، لكن ليس مع 'twenty'. والرسالة تذكر السبب أيضاً — القيمة المرفوضة مكتوبة بين علامتي اقتباس في النهاية.
فخ دقيق لكنه حقيقي جداً:
count = int(input("Count: "))إذا كتبت 12.5 فستظهر ValueError هنا أيضاً — لأن int() لا تقبل سلسلة نصية فيها فاصلة عشرية. إذا كان من الممكن أن تأتي أعداد عشرية، فاقرأها بـ float() ثم حوّلها إلى int() إذا احتجت.
لا نملك بعد كل ما يلزم لمنع هذه الأخطاء — فذلك يحتاج إلى الشروط والحلقات معاً، وكلاهما قادم في الفصول التالية. في الوقت الحالي، تعرّف على الخطأ وتعلّم قراءة رسالته.
نظّف الإدخال
يكتب الناس مسافات زائدة ويخلطون الأحرف الكبيرة والصغيرة. الطرق (methods) التي تعلمناها في الفصل السابق هي بالضبط ما نحتاجه:
full_name = input("Name: ").strip().title()
answer = input("Continue? (yes/no) ").strip().lower()
print(f"Name is {full_name}")
print(f"Answer is {answer}")Name: rafi ahmed
Continue? (yes/no) YES
Name is Rafi Ahmed
Answer is yesاجعل تشغيل .strip() على كل ما يأتي من input() عادة. لا يوجد سبب ليتعطل برنامج بسبب مسافة زائدة واحدة.
مثال كامل
bill.py:
# Ask for one order and print a small bill
print("--- Order entry ---")
customer = input("Customer name : ").strip().title()
item = input("Item : ").strip()
quantity = int(input("Quantity : "))
unit_price = float(input("Unit price : "))
subtotal = quantity * unit_price
tax = subtotal * 0.05
total = subtotal + tax
print()
print("--- Bill ---")
print(f"Customer : {customer}")
print(f"Item : {item} x {quantity}")
print(f"Subtotal : {subtotal:.2f}")
print(f"Tax (5%) : {tax:.2f}")
print(f"Total : {total:.2f}")--- Order entry ---
Customer name : rafi ahmed
Item : notebook
Quantity : 4
Unit price : 85.50
--- Bill ---
Customer : Rafi Ahmed
Item : notebook x 4
Subtotal : 342.00
Tax (5%) : 17.10
Total : 359.10أربعة مدخلات، وأربع معاملات مختلفة: الاسم نُظّف ونُسّق، واسم الصنف نُظّف فقط، والكمية حُوّلت إلى عدد صحيح، والسعر إلى عدد عشري. لكل إدخال عليك أن تقرر أمرين — ما النوع الذي تحتاجه، وكيف تنظّفه.
حالات الخطأ الشائعة وحلولها
TypeError: can only concatenate str (not "int") to str التحويل مفقود. اكتب int(input(...)) أو float(input(...)).
أردت الضرب، لكن النص يتكرر "3" * 2 تعطي "33". لم تُحوَّل القيمة إلى int. هذا الخطأ البرمجي خطير لأنه لا يُظهر أي رسالة — إذا شككت، فاطبع type().
ValueError: invalid literal for int() with base 10 ما كتبه المستخدم ليس عدداً صحيحاً — كلمة، أو عدد عشري، أو لا شيء على الإطلاق (Enter فقط). إذا كانت الأعداد العشرية ممكنة فاستخدم float().
البرنامج متوقف ولا يعرض شيئاً إنه ينتظر إدخالك. إذا لم تعطِ input() أي سؤال فلن يظهر شيء على الشاشة، ويبدو البرنامج عالقاً. أعطِ سؤالاً دائماً.
input() لا تعمل داخل المحرر بعض المحررات والمربعات البرمجية على الإنترنت لا تستطيع استقبال الإدخال. افتح الطرفية وشغّل python bill.py.
يظهر سطر فارغ إضافي بعد الضغط على Enter تأخذ input() ما كتبته ولا تحتفظ بالسطر الجديد في نهايته. السطر الفارغ الإضافي يأتي على الأرجح من print() كتبته أنت.
الخطوة ٤ من ٦ — التوقع
تحقّق من فهمك
كتب المستخدم 42 وضغط Enter. ماذا سيطبع السطر الثاني؟
value = input("Number: ")
print(type(value))- A<class 'input'>
- B<class 'int'>
- C<class 'float'>
- D<class 'str'>
كتب المستخدم 3 وطبع البرنامج Doubled: 33، دون أي خطأ. لماذا، وما الحل؟
qty = input("Quantity: ")
print("Doubled:", qty * 2)- Aكتابة `qty + qty` بدلاً من `qty * 2` ستصلح المشكلة
- Bيجب استخدام `+` بدلاً من الفاصلة في `print`
- C`input()` لا تستطيع قراءة الأرقام، لذلك نحتاج إلى دالة أخرى
- D`qty` من النوع `str`، وضرب النص في رقم يكرره — يجب كتابة `int(qty) * 2`
ماذا يحدث إذا كتب المستخدم 12.5؟
count = int(input("Count: "))
print(count + 1)- A`ValueError` — لا تقبل `int()` نصاً فيه فاصلة عشرية؛ استخدم `float()` إذا كانت الأعداد العشرية ممكنة
- Bتصبح `count` تساوي `12`، لأن `int()` تقطع كل ما بعد الفاصلة
- C`TypeError` — لأن نوع الإدخال لا يطابق نوع المتغير
- Dتصبح `count` تساوي `13`، لأن `int()` تقرّب إلى أقرب عدد صحيح
الإجابة تتطلب حساباً
سجّل الدخول للتحقق من إجاباتك
الأسئلة موجودة أعلاه، والتفكير في إجاباتها ذهنياً هو الجزء المهم. سجّل الدخول لرؤية الإجابات والتفسيرات والتلميحات ذات المستويات الثلاثة.
دورك الآن
اكتب ملفاً باسم travel.py يطرح أربعة أسئلة ويعرض حساباً صغيراً:
- اسم المسافر (منظّفاً، والحرف الأول كبير)
- عدد المسافرين (عدد صحيح)
- أجرة المسافر الواحد (عدد عشري)
- نسبة الخصم بالمئة (عدد عشري)
ثم يطبع الأجرة الإجمالية، ومقدار الخصم، والمبلغ النهائي المستحق — الثلاثة بخانتين بعد الفاصلة العشرية.
عندما يعمل، حاول كسره عمداً ثلاث مرات:
- اكتب
twoفي عدد المسافرين — أي خطأ يظهر، وماذا تقول الرسالة؟ - اكتب
2.5في عدد المسافرين — ماذا يحدث، ولماذا؟ - ضع بعض المسافات قبل الاسم وبعده — هل يبقى الناتج صحيحاً؟
إذا كانت إجابة السؤال الأخير "نعم"، فأنت تكتب الآن كوداً أفضل من المبتدئ العادي. أما حل الحالتين الأخريين فسيأتي بعد تعلّم الشروط والحلقات.
في هذه المهمة المزيد
ما قرأته أعلاه هو المهمة كاملة — لم يُحذف منها شيء. يضيف Pro:
- ما يحدث فعلياً في الكواليس — كيف ينفذ بايثون هذا الكود
- الحل الكامل للتمرين مشروحاً خطوة بخطوة
- تمارين إضافية أكثر صعوبة وتحدياً
- أسئلة المقابلات الوظيفية حول هذا الموضوع مع نموذج الإجابة
الخطوة ٦ من ٦
التحدي — اختبار الفصل
عشرة أسئلة متدرجة من السهل إلى الصعب. الأسئلة الأخيرة صعبة عن قصد.
سجّل الدخول لأداء الاختبار