الدرس 29 من دورة Python للمبتدئين

تعديل منتج أو سعره: صحّح البيانات بدل الحذف والإضافة

في الدرس السابق تعلمنا حذف منتج من القائمة. الآن سنضيف ميزة أذكى: تعديل اسم المنتج أو سعره مباشرة، مع تحديث الإجمالي بطريقة صحيحة.

المستوى: مبتدئ جدًا النتيجة: تعديل بيانات منتج مدة التطبيق: 40 - 45 دقيقة
طريقة CIT للتعلم الهادئ: لا تنظر إلى التعديل كأنه كود طويل فقط. افهم الفكرة: نختار المنتج، نقرأ بياناته القديمة، نسمح بتعديل الاسم أو السعر، ثم نحدث الإجمالي.
مهم قبل البداية: سنضيف خيارًا جديدًا في القائمة. سيصبح حذف المنتج رقم 3، وتعديل المنتج رقم 4، والخروج رقم 5.

ما النتيجة التي يجب أن تخرج بها؟

في نهاية الدرس ستكون قائمة البرنامج بهذا الشكل:

----- قائمة البرنامج -----
1. إضافة منتج
2. عرض التقرير
3. حذف منتج
4. تعديل منتج
5. خروج

وسنضيف دالة جديدة:

def edit_product(products):
    ...
    return price_difference
edit_product تختار المنتج وتعدل بياناته.
old_price السعر قبل التعديل.
price_difference الفرق الذي نضيفه إلى total.
خريطة درس تعديل منتج في Python
مفهوم تعديل منتج أو سعره في Python
1

لماذا نحتاج تعديل منتج؟

أحيانًا المستخدم لا يريد حذف المنتج. ربما كتب السعر خطأ، أو كتب الاسم ناقصًا، ويريد فقط تصحيح البيانات.

مثال:

Mouse: 500.00 ريال

والصحيح:

Mouse: 50.00 ريال
الفكرة ببساطة: الحذف مناسب عندما لا نريد المنتج. أما التعديل فهو مناسب عندما نريد المنتج لكن نريد تصحيح بياناته.
تحقق قبل الانتقال ✅ هل فهمت الفرق بين حذف منتج وتعديل منتج؟
2

أنشئ ملف الدرس التاسع والعشرين

افتح مجلد الدورة داخل VS Code:

python_course

ثم أنشئ ملفًا جديدًا باسم:

lesson_29.py

افتح الملف داخل Editor.

توقف لحظة ✅ هل ظهر ملف lesson_29.py داخل Explorer؟ إذا نعم، انتقل للخطوة التالية.
3

حدّث قائمة الأوامر

عدّل دالة print_menu لتصبح:

def print_menu():
    print()
    print("----- قائمة البرنامج -----")
    print("1. إضافة منتج")
    print("2. عرض التقرير")
    print("3. حذف منتج")
    print("4. تعديل منتج")
    print("5. خروج")
سؤال سريع 🧠 لماذا صار الخروج رقم 5؟ لأننا أضفنا أمر تعديل المنتج في رقم 4.
4

افهم فكرة فرق السعر

عند تعديل السعر، لا يكفي تغيير السعر داخل المنتج فقط. يجب أن نحدّث total أيضًا.

الحل:

price_difference = new_price - old_price

ثم في main:

total = total + price_difference
شرح فرق السعر عند تعديل منتج في Python
مثال: إذا كان السعر القديم 500 والجديد 50، فالفرق يساوي -450. عندما نضيف -450 إلى total ينقص الإجمالي بشكل صحيح.
تحقق قبل الانتقال ✅ هل فهمت لماذا نرجع فرق السعر وليس السعر الجديد فقط؟
5

اكتب دالة تعديل المنتج

أولًا: ابدأ الدالة وتأكد أن هناك منتجات:

def edit_product(products):
    if print_products(products) == False:
        return 0

ثانيًا: اطلب رقم المنتج:

    edit_prompt = "اكتب رقم المنتج المراد تعديله: "
    edit_text = input(edit_prompt).strip()

ثالثًا: حوّل الرقم إلى int:

    try:
        edit_number = int(edit_text)
    except ValueError:
        print("رقم المنتج غير صحيح")
        return 0

رابعًا: حوّل رقم المستخدم إلى index وتأكد من صحته:

    index = edit_number - 1

    if index < 0 or index >= len(products):
        print("رقم المنتج غير موجود")
        return 0

خامسًا: احفظ المنتج والسعر القديم:

    product = products[index]
    old_price = product["price"]
تحقق قبل الانتقال ✅ هل فهمت أن old_price مهم حتى نحسب الفرق بعد التعديل؟
6

عدّل الاسم إذا كتب المستخدم اسمًا جديدًا

نريد أن نعطي المستخدم خيار الإبقاء على الاسم القديم بالضغط على Enter:

    new_name = input(
        "اكتب الاسم الجديد أو Enter للإبقاء عليه: "
    ).strip()

    if new_name != "":
        product["name"] = new_name
ماذا يعني Enter هنا؟ إذا ضغط المستخدم Enter بدون كتابة اسم، فإن new_name ستكون نصًا فارغًا، ولن نغير اسم المنتج.
سؤال سريع 🧠 إذا كتب المستخدم اسمًا جديدًا، أين نحفظه؟ داخل product["name"].
7

عدّل السعر إذا كتب المستخدم سعرًا جديدًا

نقرأ السعر الجديد كنص:

    new_price_text = input(
        "اكتب السعر الجديد أو Enter للإبقاء عليه: "
    ).strip()

إذا لم يكتب شيئًا، لا نغير السعر:

    if new_price_text == "":
        print("تم تعديل المنتج")
        return 0

وإذا كتب سعرًا، نحاول تحويله إلى رقم:

    try:
        new_price = float(new_price_text)
    except ValueError:
        print("السعر غير صحيح")
        return 0

ثم نمنع السعر السالب:

    if new_price < 0:
        print("السعر لا يمكن أن يكون سالبًا")
        return 0
تحقق قبل الانتقال ✅ هل فهمت لماذا تعاملنا مع السعر مثل الدروس السابقة باستخدام try و except؟
8

احفظ السعر الجديد وارجع فرق السعر

بعد التأكد من أن السعر صحيح، نحدث المنتج:

    product["price"] = new_price

ثم نحسب فرق السعر:

    price_difference = new_price - old_price

ثم نرجع الفرق:

    print("تم تعديل المنتج")
    return price_difference
لماذا لا نرجع new_price؟ لأن total يحتوي السعر القديم بالفعل. لذلك نحتاج فقط إضافة الفرق بين الجديد والقديم.
تحقق قبل الانتقال ✅ هل فهمت أن return هنا ترجع فرق السعر حتى تستخدمه main؟
9

رتّب الكود النهائي على أجزاء

الجزء الأول: الإعدادات ودوال الحساب:

TAX_RATE = 0.15

def calculate_tax(total):
    return total * TAX_RATE

def calculate_final_total(total, tax):
    return total + tax

الجزء الثاني: إنشاء المنتج وقائمة الأوامر:

def create_product(product_name, price):
    product = {
        "name": product_name,
        "price": price
    }

    return product

def print_menu():
    print()
    print("----- قائمة البرنامج -----")
    print("1. إضافة منتج")
    print("2. عرض التقرير")
    print("3. حذف منتج")
    print("4. تعديل منتج")
    print("5. خروج")

الجزء الثالث: دالة إضافة منتج:

def add_product(products):
    name_prompt = "اسم المنتج: "
    price_prompt = "سعر المنتج: "

    product_name = input(name_prompt).strip()
    price_text = input(price_prompt).strip()

أكمل فحص السعر وإضافة المنتج:

    try:
        price = float(price_text)
    except ValueError:
        print("السعر غير صحيح، اكتب رقمًا فقط")
        return 0

    if price < 0:
        print("السعر لا يمكن أن يكون سالبًا")
        return 0

    product = create_product(product_name, price)
    products.append(product)

    print("تمت إضافة المنتج بنجاح")
    return price

الجزء الرابع: دالة عرض المنتجات:

def print_products(products):
    if len(products) == 0:
        print("لا توجد منتجات حتى الآن")
        return False

    print("----- المنتجات الحالية -----")

    for index in range(len(products)):
        product = products[index]
        name = product["name"]
        price = product["price"]
        product_number = index + 1

        print(
            f"{product_number}. {name}: "
            f"{price:.2f} ريال"
        )

    return True

الجزء الخامس: دالة حذف المنتج:

def delete_product(products):
    if print_products(products) == False:
        return 0

    delete_prompt = "اكتب رقم المنتج المراد حذفه: "
    delete_text = input(delete_prompt).strip()

    try:
        delete_number = int(delete_text)
    except ValueError:
        print("رقم المنتج غير صحيح")
        return 0

    index = delete_number - 1

أكمل الحذف وإرجاع السعر:

    if index < 0 or index >= len(products):
        print("رقم المنتج غير موجود")
        return 0

    deleted_product = products.pop(index)
    deleted_name = deleted_product["name"]

    print(f"تم حذف المنتج: {deleted_name}")

    return deleted_product["price"]

الجزء السادس: دالة تعديل المنتج:

def edit_product(products):
    if print_products(products) == False:
        return 0

    edit_prompt = "اكتب رقم المنتج المراد تعديله: "
    edit_text = input(edit_prompt).strip()

    try:
        edit_number = int(edit_text)
    except ValueError:
        print("رقم المنتج غير صحيح")
        return 0

    index = edit_number - 1

أكمل اختيار المنتج:

    if index < 0 or index >= len(products):
        print("رقم المنتج غير موجود")
        return 0

    product = products[index]
    old_price = product["price"]

عدّل الاسم إذا كتب المستخدم اسمًا جديدًا:

    new_name = input(
        "اكتب الاسم الجديد أو Enter للإبقاء عليه: "
    ).strip()

    if new_name != "":
        product["name"] = new_name

اقرأ السعر الجديد:

    new_price_text = input(
        "اكتب السعر الجديد أو Enter للإبقاء عليه: "
    ).strip()

    if new_price_text == "":
        print("تم تعديل المنتج")
        return 0

افحص السعر الجديد:

    try:
        new_price = float(new_price_text)
    except ValueError:
        print("السعر غير صحيح")
        return 0

    if new_price < 0:
        print("السعر لا يمكن أن يكون سالبًا")
        return 0

احفظ السعر وارجع الفرق:

    product["price"] = new_price

    price_difference = new_price - old_price

    print("تم تعديل المنتج")
    return price_difference

الجزء السابع: دالة التقرير:

def print_report(products, total, tax, final_total):
    if len(products) == 0:
        print("لا توجد منتجات حتى الآن")
        return

    print("----- تقرير المنتجات -----")

    for product in products:
        name = product["name"]
        price = product["price"]

        print(f"{name}: {price:.2f} ريال")

    print(f"عدد المنتجات: {len(products)}")
    print(f"الإجمالي قبل الضريبة: {total:.2f} ريال")
    print(f"الضريبة: {tax:.2f} ريال")
    print(f"الإجمالي النهائي: {final_total:.2f} ريال")

الجزء الثامن: بداية main:

def main():
    products = []
    total = 0
    menu_prompt = "اختر رقم الأمر: "

الجزء التاسع: أوامر الإضافة والحذف والتعديل:

    while True:
        print_menu()
        choice = input(menu_prompt).strip()

        if choice == "1":
            added_price = add_product(products)
            total = total + added_price

        elif choice == "3":
            deleted_price = delete_product(products)
            total = total - deleted_price

        elif choice == "4":
            price_difference = edit_product(
                products
            )
            total = total + price_difference

الجزء العاشر: عرض التقرير والخروج:

        elif choice == "2":
            tax = calculate_tax(total)
            final_total = calculate_final_total(
                total,
                tax
            )

            print_report(
                products,
                total,
                tax,
                final_total
            )

        elif choice == "5":
            print("تم إنهاء البرنامج")
            break
        else:
            print("اختيار غير صحيح، حاول مرة أخرى")

الجزء الأخير: تشغيل البرنامج:

main()
مهم جدًا: الأجزاء السابقة تُكتب في نفس ملف lesson_29.py بالترتيب. وانتبه للمسافات داخل الدوال وداخل main.
تحقق قبل الانتقال ✅ هل فهمت أن edit_product ترجع فرق السعر فقط؟
10

شغّل البرنامج

احفظ الملف:

Ctrl + S

ثم شغله:

python lesson_29.py

وإذا لم يعمل أمر python:

py lesson_29.py
تحقق قبل الانتقال ✅ هل ظهرت قائمة البرنامج وفيها 5 أوامر؟
11

اختبر تعديل السعر

أولًا: أضف منتجًا بسعر خاطئ:

اختر رقم الأمر: 1
اسم المنتج: Mouse
سعر المنتج: 500
تمت إضافة المنتج بنجاح

ثانيًا: عدّل المنتج:

اختر رقم الأمر: 4
----- المنتجات الحالية -----
1. Mouse: 500.00 ريال
اكتب رقم المنتج المراد تعديله: 1
اكتب الاسم الجديد أو Enter للإبقاء عليه:
اكتب السعر الجديد أو Enter للإبقاء عليه: 50
تم تعديل المنتج

ثالثًا: اعرض التقرير:

اختر رقم الأمر: 2
----- تقرير المنتجات -----
Mouse: 50.00 ريال
عدد المنتجات: 1
الإجمالي قبل الضريبة: 50.00 ريال
الضريبة: 7.50 ريال
الإجمالي النهائي: 57.50 ريال
ماذا تعلمت؟ البرنامج عدّل السعر داخل المنتج، ثم حدّث total باستخدام فرق السعر.
توقف لحظة ✅ هل اختبرت تعديل السعر ثم عرض التقرير؟ لا تعتمد الدرس قبل تجربة الحالتين.
12

تحدي صغير: عدّل الاسم فقط

جرّب أن تضيف منتجًا ثم تعدّل اسمه فقط بدون تعديل السعر.

اكتب الاسم الجديد أو Enter للإبقاء عليه: Wireless Mouse
اكتب السعر الجديد أو Enter للإبقاء عليه:

في هذه الحالة ترجع الدالة 0، لأن السعر لم يتغير، ولا نحتاج تعديل total.

هدف التحدي: تفهم أن تعديل الاسم لا يؤثر على الإجمالي، أما تعديل السعر فيحتاج تحديث total.
تحدي التفكير 🧠 لماذا ترجع الدالة 0 عند تعديل الاسم فقط؟ لأن total لا يتغير.

اختبار نهاية الدرس

قبل الانتقال للدرس القادم، تأكد أنك فهمت هذه النقاط:

✅ فهمت لماذا نحتاج تعديل منتج.
✅ أضفت خيار تعديل منتج إلى القائمة.
✅ كتبت دالة edit_product.
✅ استخدمت رقم المنتج للوصول إلى index.
✅ عدّلت product["name"] عند الحاجة.
✅ عدّلت product["price"] عند الحاجة.
✅ حسبت price_difference.
✅ حدّثت total بعد تعديل السعر.
إذا فهمت هذه النقاط: فأنت الآن تعطي المستخدم طريقة حقيقية لتصحيح البيانات بدون حذف وإعادة إدخال.

خلاصة الدرس

تعلمنا كيف نضيف أمر تعديل منتج إلى برنامج المشتريات. استخدمنا رقم المنتج للوصول إلى العنصر داخل القائمة، وسمحنا بتعديل الاسم أو السعر، ثم رجعنا فرق السعر حتى نحدث total.

تذكر القاعدة:

اختر المنتج
احفظ السعر القديم
عدّل الاسم أو السعر
احسب فرق السعر
حدّث total بالفرق

في الدرس القادم سننتقل إلى خطوة مهمة جدًا: حفظ وقراءة البيانات من ملف حتى لا تضيع المنتجات عند إغلاق البرنامج.