مشروع: نظام إدارة بطاقات العمل
هذا هو المشروع الختامي للمرحلة الثانية. كل المعرفة من الدروس السابقة — القوائم، القواميس، الشاملات، طرق السلاسل النصية — ستُستخدم لبناء نظام إدارة بطاقات عمل حقيقي قابل للاستخدام في سطر الأوامر. إكمال هذا المشروع يعني أنك أتقنت حقاً مفاهيم الحاويات الأساسية في بايثون.
متطلبات المشروع
سنبني "مدير بطاقات عمل" يعمل في الطرفية ويدعم الميزات التالية:
1. إضافة بطاقة — أدخل الاسم، الهاتف، البريد الإلكتروني
2. عرض جميع البطاقات — اعرضها بتنسيق جدول
3. البحث عن بطاقات — ابحث بالاسم (يدعم البحث الضبابي)
4. تعديل بطاقة — حدّث المعلومات بالاسم
5. حذف بطاقة — احذف بالاسم
6. الإحصائيات — أظهر العدد الإجمالي، إحصائيات نطاق البريد الإلكتروني
7. الخروج من البرنامج
تُخزّن البيانات باستخدام قائمة + قاموس: جميع البطاقات في قائمة، كل بطاقة كقاموس.
1. تصميم هيكل البيانات
مثال: هيكل بيانات بطاقة العمل
# كل بطاقة هي قاموس
# جميع البطاقات مخزنة في قائمة
[
{"name": "Zhang San", "phone": "13800138000", "email": "zhangsan@example.com"},
{"name": "Li Si", "phone": "13900139000", "email": "lisi@test.com"},
]
2. الكود الكامل
احفظ هذا الملف باسم card_manager.py وشغّله مباشرة:
مثال: نظام إدارة بطاقات العمل
# ====== نظام إدارة بطاقات العمل ======
# تخزين البيانات
cards = []
def show_menu():
"""اعرض القائمة الرئيسية"""
print("\n" + "=" * 35)
print("Business Card Management System")
print("=" * 35)
print("1. Add Card")
print("2. List All Cards")
print("3. Search Cards")
print("4. Modify Card")
print("5. Delete Card")
print("6. Statistics")
print("7. Exit")
print("=" * 35)
def add_card():
"""أضف بطاقة عمل"""
print("\n--- Add Card ---")
name = input("Name: ").strip()
if not name:
print("Name cannot be empty!")
return
phone = input("Phone: ").strip()
email = input("Email: ").strip()
for card in cards:
if card["name"] == name:
print(f"A card named {name} already exists. Cannot add duplicate.")
return
cards.append({"name": name, "phone": phone, "email": email})
print(f"Card for {name} added.")
def list_cards():
"""اعرض جميع البطاقات"""
if not cards:
print("\nNo cards yet.")
return
print("\n--- All Cards ---")
print(f"{'#':<4}{'Name':<10}{'Phone':<15}{'Email':<25}")
print("-" * 54)
for i, card in enumerate(cards, 1):
print(f"{i:<4}{card['name']:<10}{card['phone']:<15}{card['email']:<25}")
print(f"\nTotal: {len(cards)} cards")
def search_card():
"""ابحث عن بطاقات (يدعم البحث الضبابي)"""
if not cards:
print("\nNo cards yet.")
return
keyword = input("\nEnter name to search (partial match supported): ").strip()
if not keyword:
print("Please enter a keyword!")
return
results = [card for card in cards if keyword in card["name"]]
if not results:
print(f"No cards found matching '{keyword}'.")
return
print(f"\n--- Found {len(results)} cards ---")
for card in results:
print(f"Name: {card['name']}")
print(f"Phone: {card['phone']}")
print(f"Email: {card['email']}")
print("-" * 20)
def modify_card():
"""عدّل بطاقة"""
if not cards:
print("\nNo cards yet.")
return
name = input("\nEnter the name to modify: ").strip()
for card in cards:
if card["name"] == name:
print(f"Found card for {name}. Enter new info (press Enter to keep current):")
new_name = input(f"Name ({card['name']}): ").strip()
new_phone = input(f"Phone ({card['phone']}): ").strip()
new_email = input(f"Email ({card['email']}): ").strip()
if new_name:
card["name"] = new_name
if new_phone:
card["phone"] = new_phone
if new_email:
card["email"] = new_email
print(f"Card for {name} has been updated.")
return
print(f"No card found for {name}.")
def delete_card():
"""احذف بطاقة"""
if not cards:
print("\nNo cards yet.")
return
name = input("\nEnter the name to delete: ").strip()
for i, card in enumerate(cards):
if card["name"] == name:
confirm = input(f"Are you sure you want to delete {name}'s card? (y/n): ")
if confirm.lower() == "y":
cards.pop(i)
print(f"Card for {name} has been deleted.")
else:
print("Deletion cancelled.")
return
print(f"No card found for {name}.")
def show_stats():
"""اعرض إحصائيات البيانات"""
if not cards:
print("\nNo cards yet.")
return
print("\n--- Statistics ---")
print(f"Total cards: {len(cards)}")
domains = {}
for card in cards:
email = card["email"]
if "@" in email:
domain = email.split("@")[1]
domains[domain] = domains.get(domain, 0) + 1
if domains:
print("\nEmail domain distribution:")
for domain, count in sorted(domains.items(), key=lambda x: x[1], reverse=True):
print(f" {domain}: {count}")
has_phone = sum(1 for card in cards if card["phone"])
has_email = sum(1 for card in cards if card["email"])
print(f"\nWith phone: {has_phone}")
print(f"With email: {has_email}")
# ====== البرنامج الرئيسي ======
print("Welcome to the Business Card Management System!")
print("Enter the corresponding number to select a function.")
while True:
show_menu()
choice = input("Select option (1-7): ").strip()
if choice == "1":
add_card()
elif choice == "2":
list_cards()
elif choice == "3":
search_card()
elif choice == "4":
modify_card()
elif choice == "5":
delete_card()
elif choice == "6":
show_stats()
elif choice == "7":
print("Thank you for using! Goodbye!")
break
else:
print("Invalid choice. Please enter a number between 1 and 7.")
نهج تصميم الكود: كل ميزة مُنفّذة كدالة مستقلة. البرنامج الرئيسي يستخدم حلقة while + if-elif للتوزيع. هذا يجعل هيكل الكود واضحاً — إضافة ميزة جديدة تتطلب فقط دالة جديدة وفرع elif.
حالات الاستخدام الشائعة
- إدارة جهات الاتصال: تخزين وعرض وتعديل معلومات جهات الاتصال.
- أنظمة CRUD الأساسية: نموذج لأي نظام إدارة بيانات بسيط.
❓ أسئلة شائعة
json.dump(cards, open("data.json", "w")) للحفظ على القرص.
س:البحث الضبابي يستخدم الكلمة المفتاحية in. هل هو حساس لحالة الأحرف؟ ج:نعم. "Zhang" in "Zhang San" هو True، لكن "zhang" in "Zhang" هو False (حساس لحالة الأحرف). إذا كنت تحتاج بحثاً غير حساس لحالة الأحرف، حوّل إلى أحرف صغيرة قبل المقارنة: keyword.lower() in card["name"].lower().📖 ملخص
- نظام إدارة بطاقات العمل يستخدم قائمة لجميع البيانات وقواميس للسجلات الفردية — نمط تنظيم البيانات الأكثر شيوعاً
- التصميم المعياري: كل ميزة هي دالة مستقلة؛ البرنامج الرئيسي يستخدم حلقة للتوزيع
enumerate()يُنشئ عروض قوائم مرقمة- شاملات القوائم تنفذ البحث الضبابي
- طريقة
get()في القاموس تُستخدم لعد التكرارات - المشروع، رغم بساطته، يغطي جميع مفاهيم المرحلة 2 الأساسية
📝 تمارين
-
مبتدئ (الصعوبة ⭐): أضف ميزة جديدة لنظام البطاقات — عرض البطاقات مرتبة حسب الاسم (باستخدام
sorted()مع معاملkey). -
متوسط (الصعوبة ⭐⭐): أضف ميزة "إدارة المجموعات" لنظام البطاقات. أضف حقل
groupلكل بطاقة ("زملاء"، "أصدقاء"، "عائلة")، ثم نفذ خيار قائمة لعرض البطاقات حسب المجموعة. -
متقدم (الصعوبة ⭐⭐⭐): اكتب "نظام إدارة كتب" من الصفر دون الرجوع إلى الكود أعلاه. تشمل الميزات: إضافة كتاب (العنوان، المؤلف، السنة)، عرض الكل، البحث عن طريق المؤلف، الترتيب حسب السنة، عد الكتب حسب المؤلف. استخدم قائمة + قاموس للتخزين، كلها تعمل في سطر الأوامر.



