برنامج بلغة بايثون يقوم بقراءة قائمة أسماء أصناف، طباعة كل صنف برقمه الترتبي، ثم استخدام القاموس (dict) لحساب عدد الأصناف التي تبدأ بنفس الحرف
from typing import List, Dict
def analyze_items(items: List[str]) -> None:
"""
تقرأ قائمة أصناف، تطبع كل صنف برقمه، وتحسب عدد الأصناف التي تبدأ بكل حرف باستخدام dict.
Parameters:
items (List[str]): قائمة بأسماء الأصناف المدخلة.
"""
print("--- قائمة الأصناف المرقمة ---")
# 1. طباعة كل صنف مع رقمه الترتيبي (يبدأ من 1)
for index, item in enumerate(items, start=1):
print(f"{index}. {item}")
print("\n--- عدد الأصناف التي تبدأ بنفس الحرف ---")
# 2. إنشاء قاموس لتخزين تكرار كل حرف أول
letter_counts: Dict[str, int] = {}
for item in items:
if not item:
continue
# أخذ الحرف الأول وتحويله إلى حرف صغير لتوحيد المقارنة
first_letter = item[0].lower()
# تحديث العداد في القاموس
if first_letter in letter_counts:
letter_counts[first_letter] += 1
else:
letter_counts[first_letter] = 1
# 3. طباعة النتائج من القاموس
for letter, count in letter_counts.items():
print(f"الحرف '{letter.upper()}': عدد الأصناف التي تبدأ به هو {count}")
# تجربة البرنامج بقائمة أمثلة للأصناف
if __name__ == "__main__":
my_items = ["تفاح", "موز", "برتقال", "توت", "مانجو", "تمر", "بطاطس"]
analyze_items(my_items)
--- Item List ---
1. Apple
2. Banana
3. Orange
4. Apricot
5. Mango
6. Avocado
7. Blueberry
--- Items Count by Starting Letter ---
Letter 'A': 3 item(s)
Letter 'B': 2 item(s)
Letter 'O': 1 item(s)
Letter 'M': 1 item(s)
PS D:\study py\day001>
ثانياً: ما فائدة السطر if __name__ == "__main__":؟ وماذا يحدث لو لم تكتبه؟
هذا السطر هو أحد أهم المعايير الاحترافية في لغة بايثون، ويُعرف بـ متحكم نقطة الدخول (Entry Point Guard).
1. ما فائدته بالتحديد؟
عندما تقوم بتشغيل أي ملف بايثون، تقوم البايثون بتعيين قيمة لمتغير سحري يسمى __name__:
إذا قمت بتشغيل الملف مباشرة، فإن قيمة __name__ تصبح تلقائياً "__main__".
إذا قام ملف آخر باستيراد (import) هذا الملف كـ مكتبة، فلن تصبح قيمته "__main__" بل ستكون اسم الملف نفسه.
لذلك، عندما تكتب:
Python
if __name__ == "__main__":
my_items = ["Apple", "Banana", ...]
analyze_items(my_items)
فهذا يعني لـ بايثون: "قم بتنفيذ هذه الأوامر فقط وفقط إذا قام المستخدم بتشغيل هذا الملف مباشرة، ولكن لا تقم بتنفيذها إذا قام شخص باستيراده في ملف آخر".
2. ماذا لو لم تكتبه؟
لو قمت بحذف هذا السطر ووضعت استدعاء الدالة هكذا مباشرة في نهاية الملف:
Python
my_items = ["Apple", "Banana", ...]
analyze_items(my_items)
حين تشغيل الملف لوحده: سيُنفذ البرنامج بشكل طبيعي تماماً ولن تلاحظ أي فرق.
المشكلة الحقيقية: لو أنك في المستقبل قررت إنشاء ملف بايثون جديد واستوردت هذا الملف (import coin_flip_file) لاستخدام دواله في مشروع أكبر، فإن بايثون ستنفذ الكود وتطبع النتائج فوراً لمجرد حدوث عملية الاستيراد (import)، وهو أمر غير مرغوب فيه وغالباً ما يسبب أخطاء في البرامج الكبيرة.
لجعل البرنامج تفاعلياً بحيث يقوم المستخدم بإدخال الأصناف يدوياً عبر لوحة المفاتيح باستخدام الدالة input()، يمكننا إنشاء حلقة تكرارية (while loop) تطلب من المستخدم إدخال الأصناف واحداً تلو الآخر، وتتوقف عندما يكتب المستخدم كلمة معينة مثل 'done' (انتهيت).
إليك البرنامج كاملاً مع الحفاظ على المدخلات والمخرجات باللغة الإنجليزية، والشرح باللغة العربية:
Enter item: done
--- Item List ---
1. sdfsdf
2. dddd
3. g
4. yu
5. hjhj
6. gfhfgh
7. hf
8. aaa
9. a1
--- Items Count by Starting Letter ---
Letter 'S': 1 item(s)
Letter 'D': 1 item(s)
Letter 'G': 2 item(s)
Letter 'Y': 1 item(s)
Letter 'H': 2 item(s)
Letter 'A': 2 item(s)
PS D:\study py\day001>
def analyze_items(items: List[str]) -> None ليه كتبنا سطر كده في تعريف الدالة؟ .
هذا السطر يُعرف بـ **توقيع الدالة (Function Signature)**، ويتضمن ما يُسمى **تلميحات الأنواع (Type Hints)** في لغة بايثون.
دعنا نقسم هذا السطر إلى جزأين أساسيين لنفهم فائدة كتابته بالتفصيل:
### 1. الجزء الأول: المدخلات `(items: List[str])`
* **معناه:** يُخبر هذا الجزء بايثون (وكل من يقرأ الكود) أن الدالة `analyze_items` تتوقع استقبال وسيط واحد فقط اسمه `items`، وأن هذا الوسيط يجب أن يكون **قائمة (List)** عناصرها عبارة عن **نصوص (Strings)**.
* **الفوائد:**
* **مساعدة محرر الكود (IDEs):** برامج مثل VS Code ستفهم أن `items` عبارة عن قائمة نصوص، وبالتالي ستقترح عليك الدوال المناسبة للنصوص عندما تكتب الكود داخلياً.
* **منع الأخطاء:** إذا قام مبرمج آخر بتمرير رقم صحيح بدلاً من قائمة نصوص، ستنذره بيئة التطوير بأن هناك خطأ في نوع البيانات المتوقع.
---
### 2. الجزء الثاني: المخرجات `-> None`
* **معناه:** السهم `->` وما بعده يُحدد **نوع القيمة المُرجعة (Return Type)** من الدالة. كتابة `-> None` تعني بوضوح تام: **"هذه الدالة تنفذ عملية معينة (مثل الطباعة)، ولكنها لا تُرجع أي قيمة مفيدة (لا تحتوي على `return` يعيد بيانات)، وبالتالي فإن قيمتها المُرجعة هي `None` تلقائياً"**.
* **الفوائد:**
* توثيق فوري لوظيفة الدالة؛ فالمبرمج يعرف بمجرد النظر أنها تفعل شيئاً (مثل عرض نتائج) ولا تُرجع متغيراً ليتم تخزينه واستخدامه لاحقاً.
---
### الخلاصة:
هذا السطر ليس إجبارياً لتشغيل الكود في بايثون (لأن بايثون لغة ديناميكية)، ولكنه يُعتبر **معياراً احترافياً للبرمجة النظيفة (Clean Code)** لأنه يجعل الكود منظماً، مقروءاً، وأسهل في اكتشاف الأخطاء مبكراً.
