القواميس والمجموعات

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


1. ما هو القاموس

يُعرّف القاموس بأقواس متعرجة {}، يحتوي على مجموعة من أزواج المفتاح-القيمة، مفصولة بنقطتين.

PYTHON
# تعريف قاموس
student = {
    "name": "Alice",
    "age": 20,
    "city": "Beijing"
}

print(student)               # {'name': 'Alice', 'age': 20, 'city': 'Beijing'}
print(type(student))         # <class 'dict'>
💡 فكر في القاموس كقاموس حقيقي: "المفاتيح" هي كلمات الإدخال، "القيم" هي التعريفات. ابحث عن مفتاح وستحصل على قيمته فوراً. عمليات البحث في القاموس سريعة جداً — سواء كان هناك 10 إدخالات أو 100,000، السرعة متقاربة.

عمليات CRUD الأساسية

PYTHON
# أنشئ قاموساً
user = {}

# أضف / عدّل أزواج المفتاح-القيمة
user["name"] = "Alice"
user["age"] = 25
print(user)                 # {'name': 'Alice', 'age': 25}

# عدّل مفتاحاً موجوداً
user["age"] = 26
print(user)                 # {'name': 'Alice', 'age': 26}

# اقرأ قيمة
print(user["name"])         # Alice
# print(user["email"])      # KeyError! مفتاح غير موجود يُثير خطأ

# استخدم get() للوصول الآمن — يُرجع القيمة الافتراضية إذا المفتاح غير موجود
print(user.get("email"))             # None — غير موجود، يُرجع None
print(user.get("email", "not set"))  # not set — قيمة افتراضية مخصصة

# احذف زوج مفتاح-قيمة
del user["age"]
print(user)                 # {'name': 'Alice'}
⚠️ ملاحظة: استخدام dict["non_existent_key"] يُثير KeyError. استخدم get() لتجنب هذا — يُرجع None أو القيمة الافتراضية التي تحددها.

مثال: إدارة معلومات الطالب (الصعوبة ⭐)

PYTHON
# خزّن معلومات الطالب الكاملة في قاموس
student = {
    "name": "Bob",
    "id": "2024001",
    "scores": {"Chinese": 85, "Math": 92, "English": 78},
    "is_active": True
}

# اقرأ المعلومات الأساسية
print(f"Name: {student['name']}")
print(f"ID: {student['id']}")

# اقرأ من قاموس متداخل
math_score = student["scores"]["Math"]
print(f"Math score: {math_score}")

# وصول آمن باستخدام get
phone = student.get("phone", "not filled")
print(f"Phone: {phone}")
▶ جرّب الكود

المخرجات:

TEXT
Name: Bob
ID: 2024001
Math score: 92
Phone: not filled

2. طرق القاموس الشائعة

الحصول على جميع المفاتيح، القيم، وأزواج المفتاح-القيمة

PYTHON
user = {"name": "Alice", "age": 25, "city": "Beijing"}

print(user.keys())      # dict_keys(['name', 'age', 'city'])
print(user.values())    # dict_values(['Alice', 25, 'Beijing'])
print(user.items())     # dict_items([('name', 'Alice'), ('age', 25), ('city', 'Beijing')])

# الطريقة الأكثر شيوعاً للتكرار على قاموس
for key, value in user.items():
    print(f"{key} = {value}")

المخرجات:

TEXT
name = Alice
age = 25
city = Beijing

pop() و setdefault()

PYTHON
# pop() — أزل وأرجع القيمة لمفتاح
user = {"name": "Alice", "age": 25, "city": "Beijing"}
city = user.pop("city")
print(f"Removed city: {city}")      # Removed city: Beijing
print(user)                          # {'name': 'Alice', 'age': 25}

# pop() يمكنه تحديد قيمة افتراضية، متجنباً KeyError
email = user.pop("email", "no email")
print(email)                         # no email — المفتاح غير موجود، يُرجع الافتراضي

# setdefault() — إذا كان المفتاح موجوداً، أرجع قيمته؛ إذا لم يكن، أدخل الافتراضي
user = {"name": "Alice"}
result = user.setdefault("age", 18)
print(user)                          # {'name': 'Alice', 'age': 18}

# إذا كان المفتاح موجوداً بالفعل، setdefault لا يعدله
result = user.setdefault("name", "Bob")
print(user)                          # {'name': 'Alice', 'age': 18} — لم يتغير

update() — دمج القواميس

PYTHON
# ادمج قاموسين
defaults = {"theme": "light", "lang": "en", "font_size": 14}
custom = {"theme": "dark", "font_size": 16}

defaults.update(custom)    # custom يكتب فوق المفاتيح المتطابقة في defaults
print(defaults)            # {'theme': 'dark', 'lang': 'en', 'font_size': 16}

مثال: عد الكلمات (الصعوبة ⭐⭐)

PYTHON
# عد ظهور الكلمات في جملة
text = "apple banana apple orange banana apple"

word_count = {}
for word in text.split():
    # إذا كانت الكلمة موجودة بالفعل في القاموس، زد؛ وإلا، اجعلها 1
    word_count[word] = word_count.get(word, 0) + 1

print(word_count)          # {'apple': 3, 'banana': 2, 'orange': 1}

# الإخراج باستخدام items()
for word, count in word_count.items():
    print(f"{word}: {count} times")
▶ جرّب الكود

المخرجات:

TEXT
apple: 3 times
banana: 2 times
orange: 1 times

3. التكرار على القاموس والتداخل

ثلاث طرق للتكرار على قاموس

PYTHON
user = {"name": "Alice", "age": 25, "city": "Beijing"}

# الطريقة 1: التكرار على المفاتيح
for key in user:                # تعادل for key in user.keys():
    print(f"{key}: {user[key]}")

# الطريقة 2: التكرار على القيم
for value in user.values():
    print(value)

# الطريقة 3: التكرار على أزواج المفتاح-القيمة (موصى به)
for key, value in user.items():
    print(f"{key} → {value}")

القواميس المتداخلة

PYTHON
# قاموس متداخل — تخزين سجلات طلاب متعددة
students = {
    "1001": {"name": "Alice", "scores": [85, 90, 78]},
    "1002": {"name": "Bob", "scores": [92, 88, 95]},
    "1003": {"name": "Charlie", "scores": [76, 85, 82]},
}

# التكرار على قاموس متداخل
for sid, info in students.items():
    name = info["name"]
    avg = sum(info["scores"]) / len(info["scores"])
    print(f"{sid} {name}: Average {avg:.1f}")

المخرجات:

TEXT
1001 Alice: Average 84.3
1002 Bob: Average 91.7
1003 Charlie: Average 81.0

4. ما هي المجموعة

تُعرّف المجموعة بأقواس متعرجة {} أو set(). تبدو كقاموس لكن لا توجد قيم، فقط مفاتيح. المجموعات: عناصر فريدة، غير مرتبة.

PYTHON
# تعريف مجموعة
fruits = {"apple", "banana", "orange", "apple"}    # التكرارات تُزال تلقائياً
print(fruits)            # {'orange', 'apple', 'banana'} — الترتيب قد يختلف

# أنشئ مجموعة من قائمة
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers)           # {1, 2, 3} — التكرارات أزيلت

# المجموعة الفارغة يجب أن تستخدم set()، وليس {} ({} هي قاموس فارغ)
empty_set = set()
print(type(empty_set))   # <class 'set'>
💡 الاستخدام الأكثر شيوعاً للمجموعات هو إزالة التكرارات: list(set(list_name)) يزيل التكرارات بسرعة. لكن لاحظ أن المجموعات غير مرتبة، لذا الترتيب الأصلي يُفقد.

عمليات المجموعة الأساسية

PYTHON
# إضافة وإزالة
s = set()
s.add("apple")
s.add("banana")
s.add("apple")           # إضافة مكررة ليس لها تأثير
print(s)                 # {'apple', 'banana'}

s.discard("apple")       # إزالة؛ لا خطأ إذا لم يُعثر عليه
print(s)                 # {'banana'}

# s.remove("non_existent")   # سيُثير KeyError!

5. عمليات المجموعات

هذا هو المجال الذي تتألق فيه المجموعات حقاً — التقاطع والاتحاد والفرق الرياضية:

PYTHON
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}

# التقاطع — عناصر موجودة في كلتا المجموعتين
print(a & b)             # {4, 5}
print(a.intersection(b)) # نفس الشيء

# الاتحاد — جميع العناصر من كلا المجموعتين (بدون تكرار)
print(a | b)             # {1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b))        # نفس الشيء

# الفرق — عناصر في a وليست في b
print(a - b)             # {1, 2, 3}
print(a.difference(b))   # نفس الشيء

# الفرق المتماثل — عناصر في a أو b ولكن ليس كلاهما
print(a ^ b)             # {1, 2, 3, 6, 7, 8}

مثال: تحليل أذونات المستخدم (الصعوبة ⭐⭐⭐)

PYTHON
# محاكاة علاقات مستخدمي منصة اجتماعية
all_users = {"Alice", "Bob", "Charlie", "Diana", "Eve"}
vip_users = {"Bob", "Diana", "Eve"}
blocked_users = {"Diana"}

# ابحث عن "المستخدمين العاديين الذين ليسوا VIP"
normal_users = all_users - vip_users - blocked_users
print(f"Normal users: {normal_users}")

# ابحث عن "VIP النشطين (غير المحظورين)"
active_vip = vip_users - blocked_users
print(f"Active VIPs: {active_vip}")

# ابحث عن "المستخدمين المحظورين الذين هم VIP"
blocked_vip = vip_users & blocked_users
print(f"Blocked VIPs: {blocked_vip}")

# ابحث عن "جميع المستخدمين الذين يحتاجون إشعاراً (VIP + محظورين)"
notify_users = vip_users | blocked_users
print(f"Users to notify: {notify_users}")
▶ جرّب الكود

المخرجات:

TEXT
Normal users: {'Alice', 'Charlie'}
Active VIPs: {'Bob', 'Eve'}
Blocked VIPs: {'Diana'}
Users to notify: {'Bob', 'Diana', 'Eve'}

حالات الاستخدام الشائعة


❓ أسئلة شائعة

س متى يجب استخدام القاموس مقابل القائمة؟
ج إذا كنت تبحث عن بيانات "بالاسم" (مفتاح)، استخدم القاموس — مثلاً، البحث عن طالب بمعرفه. إذا كنت تحتاج فقط للوصول إلى البيانات "بالتسلسل"، استخدم القائمة — مثلاً، عربة تسوق. عمليات البحث في القاموس أسرع بكثير من القوائم — الفرق كبير مع مجموعات البيانات الكبيرة (آلاف العناصر). ⚠️ س:ما القيود التي تفرضها مفاتيح القاموس؟ لماذا لا يمكن للقوائم أن تكون مفاتيح؟ ج:مفاتيح القاموس يجب أن تكون غير قابلة للتعديل — الأرقام والسلاسل النصية والصفوف تعمل. القوائم قابلة للتعديل، لذا لا يمكن أن تكون مفاتيح. إذا كانت القائمة مفتاحاً وتغير محتواها، لن يتمكن القاموس من العثور عليها. هذا هو نفس السبب الذي يجعل الصفوف يمكن أن تكون مفاتيح — إنها غير قابلة للتعديل، لذا فهي آمنة. س:ما الفرق بين discard() و remove()؟ ج:remove() يُثير KeyError إذا العنصر غير موجود. discard() لا يفعل — يزيل إذا كان موجوداً، أو لا يفعل شيئاً بصمت إذا لم يكن. إذا كنت غير متأكد من وجود عنصر، استخدم discard() للأمان.

📖 ملخص

  • القواميس تستخدم {}، تخزّن أزواج المفتاح-القيمة، وتبحث عن القيم بالمفتاح بسرعة
  • العمليات الأساسية: dict[key] قراءة/كتابة، get() قراءة آمنة، del حذف
  • الطرق الشائعة: keys()، values()، items() للتكرار؛ pop() إزالة وإرجاع؛ update() دمج
  • setdefault() يُرجع القيمة الموجودة أو يُدخل قيمة افتراضية
  • قيم القاموس يمكن أن تكون أي نوع، بما في ذلك القوائم والقواميس — مما يتيح هياكل متداخلة
  • المجموعات تستخدم {} أو set()، فريدة وغير مرتبة، أساساً لإزالة التكرارات والعمليات الرياضية
  • عمليات المجموعات: & تقاطع، | اتحاد، - فرق، ^ فرق متماثل

📝 تمارين

  1. أساسي (الصعوبة ⭐): أنشئ قاموساً لمعلوماتك الشخصية (الاسم، العمر، المدينة، الهواية). استخدم get() لقراءة حقل "الوظيفة" (أرجع "غير محدد" إذا كان مفقوداً). استخدم items() لإخراج جميع أزواج المفتاح-القيمة.

  2. متوسط (الصعوبة ⭐⭐): بالنظر إلى الجملة "hello world hello python world hello"، احسب عدد مرات ظهور كل كلمة وابحث عن الكلمة الأكثر تكراراً. تلميح: استخدم قاموساً للعد؛ استخدم max(dict.items(), key=lambda x: x[1]) للعثور على القيمة القصوى.

  3. تحدي (الصعوبة ⭐⭐⭐): اكتب برنامج "دفتر عناوين بسيط." استخدم قاموساً (الاسم ← رقم الهاتف). ادعم: add Alice 13800138000، del Alice، find Alice، all (عرض الكل). استخدم while True؛ exit للخروج. تلميح: استخدم split() لتحليل الأوامر.

100%