شرح دالة enumerate في بايثون: index والعنصر معًا

شرح دالة enumerate في بايثون للحصول على index والعنصر أثناء المرور على List

إذا كنت تمر على عناصر List في بايثون وتحتاج إلى معرفة رقم كل عنصر وقيمته في الوقت نفسه، فدالة enumerate() هي واحدة من أوضح الأدوات لهذا الغرض.

بدل كتابة range(len(list)) ثم استخدام رقم الفهرس للوصول إلى العنصر، تستطيع enumerate() إعطاءك عدادًا والعنصر مباشرة داخل حلقة for.

في هذا الدرس من بايثون العرب سنشرح كيف تعمل enumerate()، والفرق بينها وبين range() وlen()، وكيف تستخدم start بطريقة صحيحة دون الخلط بين رقم العرض والفهرس الحقيقي للقائمة.

وسنوضح أيضًا متى لا تحتاج إلى enumerate() أصلًا، ومتى تكون حلقة for العادية أو range() أنسب، حتى تختار الأسلوب الصحيح بدل استخدام الدالة في كل حالة.

{getToc} $title={محتوى المقال}

{alertInfo} إذا كنت تحتاج إلى قيمة العنصر فقط فاستخدم for item in list. أما إذا كنت تحتاج إلى رقم مع العنصر أثناء المرور، فغالبًا enumerate() هي الأنسب.

قبل المتابعة، يفيد أن تكون مرتاحًا مع القوائم Lists في بايثون و الحلقات Loops في بايثون.

ما هي دالة enumerate في بايثون؟

دالة enumerate() هي دالة مدمجة في بايثون تستقبل شيئًا قابلًا للتكرار مثل List، وتعيد كائن enumerate. وعند المرور عليه، تحصل في كل مرة على زوج يحتوي على عداد وقيمة العنصر.

names = ["Ahmed", "Sara", "Omar"]

print(list(enumerate(names)))

الناتج:

[(0, 'Ahmed'), (1, 'Sara'), (2, 'Omar')]

لاحظ أن كل عنصر في النتيجة عبارة عن زوج: الرقم أولًا، ثم القيمة. والقيمة الافتراضية لبداية العداد هي 0.

طريقة عمل enumerate في بايثون وإرجاع رقم العنصر وقيمته في كل دورة

استخدام enumerate داخل for loop

الاستخدام الأكثر شيوعًا هو تفكيك الرقم والعنصر مباشرة داخل حلقة for:

names = ["Ahmed", "Sara", "Omar"]

for index, name in enumerate(names):
    print(index, name)

الناتج:

0 Ahmed
1 Sara
2 Omar

هنا المتغير index يساوي 0 ثم 1 ثم 2، بينما المتغير name يحمل العنصر المقابل في القائمة.

لماذا enumerate أوضح من range(len())؟

يمكنك الحصول على النتيجة نفسها باستخدام range() وlen():

names = ["Ahmed", "Sara", "Omar"]

for i in range(len(names)):
    print(i, names[i])

هذا الكود صحيح، لكنك تحصل أولًا على الرقم ثم تستخدمه للوصول إلى العنصر عبر names[i]. إذا كان هدفك فقط الحصول على الرقم والعنصر أثناء المرور، فإن enumerate() تعبر عن الفكرة مباشرة.

استخدام range وlen للوصول إلى index وعناصر List في بايثون
الحالة الأسلوب الأنسب لماذا؟
أحتاج إلى قيمة العنصر فقط for item in items الأبسط ولا تحتاج إلى رقم
أحتاج إلى الرقم والعنصر معًا enumerate(items) تعطيك الاثنين مباشرة
أحتاج إلى تسلسل أرقام أو حسابات على الفهارس نفسها range(...) تتعامل مباشرة مع الأرقام

تغيير بداية العداد باستخدام start

يمكنك تغيير الرقم الذي يبدأ منه عداد enumerate() باستخدام المعامل start. وهذا مفيد عند عرض قائمة مرقمة للمستخدم.

names = ["Ahmed", "Sara", "Omar"]

for number, name in enumerate(names, start=1):
    print(number, name)

الناتج:

1 Ahmed
2 Sara
3 Omar
{alertWarning} مهم: start=1 لا يغيّر الفهرس الحقيقي لعناصر القائمة. هو يغيّر عداد enumerate() فقط. فالعنصر "Ahmed" ما يزال في الفهرس الحقيقي 0.

الفرق بين index الحقيقي ورقم العرض

هذا الفرق مهم جدًا للمبتدئ. في المثال التالي، نعرض رقمًا يبدأ من 1 للمستخدم، لكننا نطبع أيضًا الفهرس الحقيقي للقائمة:

names = ["Ahmed", "Sara", "Omar"]

for index, name in enumerate(names):
    display_number = index + 1
    print(f"رقم العرض: {display_number} - index: {index} - {name}")

بهذه الطريقة يبقى معنى index دقيقًا، ونستخدم متغيرًا آخر عندما نريد ترقيمًا مناسبًا للعرض.

مقارنة enumerate وrange مع len في بايثون للحصول على index والعنصر

مثال عملي: عرض قائمة مهام مرقمة

tasks = [
    "Learn Python",
    "Practice loops",
    "Build a small project"
]

for number, task in enumerate(tasks, start=1):
    print(f"{number}. {task}")

الناتج:

1. Learn Python
2. Practice loops
3. Build a small project

هنا تسمية المتغير number أفضل من index لأننا بدأنا العداد من 1 ونستخدمه للعرض فقط.

ماذا تعيد enumerate فعلًا؟

إذا كتبت متغيرًا واحدًا بدل تفكيك القيمتين، ستلاحظ أن كل عنصر ناتج هو tuple مكوّن من رقم وقيمة:

names = ["Ahmed", "Sara"]

for pair in enumerate(names):
    print(pair)

الناتج:

(0, 'Ahmed')
(1, 'Sara')

لذلك كتابة for index, name in enumerate(names) هي عملية تفكيك مباشرة لهذه الأزواج.

هل enumerate تعمل مع List فقط؟

لا. enumerate() تعمل مع أي كائن قابل للتكرار، مثل Tuple أو النصوص، وليست مقصورة على القوائم. لكننا نركز هنا على List لأن هذا هو الاستخدام الأكثر ارتباطًا بموضوع المقال.

for index, letter in enumerate("Python"):
    print(index, letter)

استخدام enumerate للعثور على عنصر أثناء المرور

إذا كنت تمر على قائمة وتريد تنفيذ شيء عند العثور على قيمة معينة، يمكنك استخدام enumerate() لمعرفة موقعها أثناء الحلقة:

products = ["Keyboard", "Mouse", "Monitor", "USB Cable"]

for index, product in enumerate(products):
    if product == "Monitor":
        print(f"Found at index {index}")
        break

الناتج:

Found at index 2

أما إذا كان هدفك الأساسي هو البحث داخل القائمة باستخدام in أو index()، فراجع بايثون بالمثال 10: البحث عن عنصر داخل List.

enumerate لا تعني list.index()

هناك فرق بين الأداتين:

الأداة ماذا تفعل؟ متى تستخدمها؟
enumerate(items) تعطيك رقمًا وقيمة أثناء المرور على العناصر عندما تعمل داخل حلقة وتحتاج الاثنين
items.index(value) تبحث عن أول موقع لقيمة معينة داخل القائمة عندما تريد موقع قيمة معروفة

أخطاء شائعة عند استخدام enumerate

1. اعتبار start=1 فهرسًا حقيقيًا

إذا استخدمت start=1 فلا تسمِّ الرقم الناتج index إذا كنت ستستخدمه للوصول إلى القائمة، لأنه أصبح عدادًا يبدأ من 1 وليس الفهرس الحقيقي.

2. توقع List مباشرة من enumerate

كتابة enumerate(names) لا تنشئ List جديدة. إذا أردت رؤية الأزواج كلها للتعلّم أو الفحص، استخدم list(enumerate(names)).

3. استخدام enumerate عندما لا تحتاج الرقم

إذا كنت تحتاج إلى العنصر فقط، فهذا أبسط:

names = ["Ahmed", "Sara", "Omar"]

for name in names:
    print(name)

4. استخدام فهارس يدوية دون حاجة

إذا كنت تكتب range(len(items)) فقط للحصول على العنصر ورقمه، فراجع إن كانت enumerate() ستجعل الكود أوضح. وهي تساعد أيضًا على تجنب بعض أخطاء الفهارس؛ راجع حل خطأ IndexError list index out of range.

استخدام enumerate مع start=1 لترقيم عناصر List للمستخدم في بايثون

أسئلة شائعة عن enumerate في بايثون

من أي رقم تبدأ enumerate؟

تبدأ من 0 افتراضيًا، ويمكن تغيير العداد باستخدام start.

هل start=1 يجعل أول عنصر في index رقم 1؟

لا. هو يجعل عداد enumerate() يبدأ من 1، لكن الفهرس الحقيقي لأول عنصر في List يبقى 0.

هل enumerate ترجع List؟

لا. ترجع كائن enumerate قابلًا للتكرار. يمكنك تحويله إلى List باستخدام list() إذا احتجت ذلك.

متى أستخدم enumerate بدل range؟

استخدم enumerate() عندما تحتاج إلى الرقم والعنصر أثناء المرور. واستخدم range() عندما تكون الأرقام نفسها هي ما تريد توليده أو التحكم فيه.

روابط مفيدة

خلاصة المقال

دالة enumerate() مفيدة عندما تحتاج إلى المرور على عناصر iterable والحصول على عداد وقيمة العنصر في الوقت نفسه. تبدأ من الصفر افتراضيًا، ويمكن تغيير بداية العداد باستخدام start.

استخدمها بدل range(len(list)) عندما يكون هدفك فقط قراءة رقم مع العنصر، وتذكر أن start=1 يغيّر العداد وليس الفهرس الحقيقي للقائمة.

{alertSuccess} القاعدة العملية: إذا احتجت إلى العنصر فقط فاستخدم for item in items، وإذا احتجت إلى الرقم والعنصر معًا فاستخدم enumerate().

تمرين بسيط لك

لديك قائمة درجات. اطبع رقم الطالب بدءًا من 1 مع درجته، ثم اطبع أيضًا الفهرس الحقيقي لكل درجة.

grades = [85, 92, 78, 90]

for index, grade in enumerate(grades):
    student_number = index + 1
    print(f"Student {student_number} - index {index} - grade {grade}")

إرسال تعليق

أحدث أقدم