دالة zip() في Python تربط العناصر المتقابلة من قائمتين أو أكثر، وتُرجع iterator من tuples: العنصر الأول مع الأول، والثاني مع الثاني، وهكذا. لذلك فهي مناسبة عندما تريد المرور على أكثر من قائمة معًا أو تحويل قائمتين إلى أزواج مترابطة.
افتراضيًا تتوقف zip() عند أقصر iterable إذا اختلفت الأطوال. وإذا كان تساوي الأطوال شرطًا مهمًا في برنامجك، فيمكنك استخدام strict=True في Python 3.10 فأحدث حتى يظهر ValueError بدل تجاهل العناصر الزائدة بصمت.
في هذا الدرس من بايثون العرب سنشرح دالة zip() للمبتدئين، ونستخدمها مع for والقوائم، ونحوّل نتيجتها إلى list وdict، ثم نتعلم التعامل مع اختلاف الأطوال وفك الدمج باستخدام zip(*...).
الفكرة المختصرة: استخدم zip() عندما تكون لديك بيانات متقابلة في أكثر من iterable وتريد التعامل معها معًا بالترتيب نفسه. {alertInfo}
{getToc} $title={محتوى المقال}
ما هي دالة zip في Python؟
دالة zip() هي دالة جاهزة في Python تُستخدم لدمج أكثر من كائن قابل للتكرار، مثل القوائم Lists أو النصوص Strings أو الصفوف Tuples.
عندما تمرر قائمتين إلى zip() فإنها لا تدمجهما كقائمة واحدة، بل تربط العناصر المتقابلة معًا على شكل أزواج.
names = ["Ali", "Sara", "Omar"]
scores = [90, 85, 77]
result = zip(names, scores)
print(list(result))
الناتج:
[('Ali', 90), ('Sara', 85), ('Omar', 77)]
لاحظ أن zip() جمعت كل اسم مع الدرجة المقابلة له.
لماذا نستخدم zip بدل التكرار بالفهرس؟
قبل أن تعرف zip() قد تكتب كودًا يعتمد على الفهرس للوصول إلى عنصر من القائمة الأولى وعنصر من القائمة الثانية. إذا كنت ما زلت تتعلم هذه الأساسيات، راجع شرح Lists في Python وشرح Loops في Python.
names = ["Ali", "Sara", "Omar"]
scores = [90, 85, 77]
for i in range(len(names)):
print(names[i], scores[i])
الكود يعمل، لكنه أطول ويحتاج إلى فهم الفهارس جيدًا. باستخدام zip() يصبح الكود أوضح:
names = ["Ali", "Sara", "Omar"]
scores = [90, 85, 77]
for name, score in zip(names, scores):
print(name, score)
هذا الأسلوب أسهل للقراءة، وأقرب إلى التفكير الطبيعي: لكل اسم، خذ الدرجة المقابلة له.
نصيحة مهمة: عندما تريد المرور على قائمتين في نفس الوقت، غالبًا ستكونzip()أوضح من استخدامrange(len()). {alertSuccess}
مثال عملي: عرض أسماء الطلاب ودرجاتهم
لنفترض أن لديك قائمة بأسماء الطلاب وقائمة أخرى بدرجاتهم، وتريد طباعة كل طالب مع درجته.
students = ["أحمد", "ليلى", "مريم"]
grades = [95, 88, 91]
for student, grade in zip(students, grades):
print(student, "حصل على", grade)
الناتج:
أحمد حصل على 95
ليلى حصل على 88
مريم حصل على 91
هذا المثال مفيد جدًا في التطبيقات التعليمية، الجداول، معالجة البيانات، والتقارير البسيطة.
تحويل نتيجة zip إلى list
من الأشياء التي تربك المبتدئين أن طباعة zip() مباشرة لا تعرض العناصر بالشكل المتوقع.
a = [1, 2, 3]
b = ["A", "B", "C"]
print(zip(a, b))
قد يظهر لك شيء شبيه بهذا:
<zip object at 0x...>
هذا ليس خطأ. في Python 3 تُرجع zip() iterator ينتج tuples عند الطلب، وليس قائمة جاهزة. إذا أردت حفظ جميع الأزواج أو الوصول إليها أكثر من مرة، حوّل النتيجة إلى list.
a = [1, 2, 3]
b = ["A", "B", "C"]
result = list(zip(a, b))
print(result)
الناتج:
[(1, 'A'), (2, 'B'), (3, 'C')]
وتذكّر أن iterator يُستهلك أثناء المرور عليه. لذلك إذا أردت إعادة استخدام النتيجة، خزّنها في list بدل الاحتفاظ بكائن zip نفسه:
pairs = zip([1, 2], ["A", "B"])
print(list(pairs))
print(list(pairs)) # [] لأن iterator استُهلك
فك الدمج باستخدام zip(*pairs)
يمكن استخدام zip() بالعكس أيضًا لفصل قائمة من الأزواج إلى مجموعات مستقلة. نستخدم معامل فك التجميع * لتمرير الأزواج إلى zip():
pairs = [
("Ali", 90),
("Sara", 85),
("Omar", 77)
]
names, scores = zip(*pairs)
print(names)
print(scores)
الناتج يكون tuples:
('Ali', 'Sara', 'Omar')
(90, 85, 77)
تحويل قائمتين إلى Dictionary باستخدام zip
من أشهر استخدامات zip() في Python تحويل قائمتين إلى قاموس Dictionary.
القائمة الأولى تكون المفاتيح، والقائمة الثانية تكون القيم.
keys = ["name", "age", "city"]
values = ["Ali", 20, "Sanaa"]
user = dict(zip(keys, values))
print(user)
الناتج:
{'name': 'Ali', 'age': 20, 'city': 'Sanaa'}
هذا المثال مهم جدًا؛ لأن القواميس تُستخدم كثيرًا في بايثون عند تنظيم البيانات. إذا لم تكن مرتاحًا مع القواميس بعد، يمكنك مراجعة درس: شرح القواميس Dictionaries في Python للمبتدئين.
استخدام zip مع أكثر من قائمتين
يمكنك استخدام zip() مع أكثر من قائمتين. مثلًا: قائمة أسماء، وقائمة أعمار، وقائمة مدن.
names = ["Ali", "Sara", "Omar"]
ages = [20, 22, 19]
cities = ["Sanaa", "Amman", "Cairo"]
for name, age, city in zip(names, ages, cities):
print(name, age, city)
الناتج:
Ali 20 Sanaa
Sara 22 Amman
Omar 19 Cairo
كل دورة في الحلقة تأخذ عنصرًا من كل قائمة بالترتيب نفسه.
ماذا يحدث إذا كانت القوائم بأطوال مختلفة؟
إذا كانت القوائم غير متساوية في عدد العناصر، فإن zip() تتوقف عند أقصر قائمة.
names = ["Ali", "Sara", "Omar"]
scores = [90, 85]
for name, score in zip(names, scores):
print(name, score)
الناتج:
Ali 90
Sara 85
لاحظ أن Omar لم يظهر؛ لأن قائمة الدرجات تحتوي على عنصرين فقط.
تنبيه: إذا كانت القوائم عندك بأطوال مختلفة، تأكد أن تجاهل العناصر الزائدة هو السلوك الذي تريده فعلًا. {alertWarning}
استخدام strict=True لاكتشاف اختلاف الأطوال
إذا كان من المفترض أن تكون القوائم متساوية في الطول، فاستخدم strict=True في Python 3.10 فأحدث. عند اختلاف الأطوال سيظهر ValueError بدل إهمال العناصر الزائدة بصمت:
names = ["Ali", "Sara", "Omar"]
scores = [90, 85]
result = list(
zip(names, scores, strict=True)
)
أما إذا كنت تريد الاحتفاظ بكل العناصر حتى نهاية أطول iterable مع ملء القيم الناقصة، فاستخدم itertools.zip_longest() بدل zip().
متى أستخدم zip في Python؟
استخدم zip() عندما تكون لديك بيانات مترابطة في أكثر من قائمة، وتريد التعامل مع العناصر المتقابلة معًا.
| الحالة | هل zip مناسبة؟ | مثال |
|---|---|---|
| قائمة أسماء وقائمة درجات | نعم | ربط كل طالب بدرجته |
| قائمة مفاتيح وقائمة قيم | نعم | إنشاء Dictionary |
| تكرار على قائمة واحدة فقط | ليست ضرورية | استخدم for loop عادية |
| تحتاج رقم الفهرس مع القيمة | ربما لا | استخدم enumerate |
إذا كنت تريد رقم الفهرس أثناء التكرار، فالأفضل غالبًا استخدام enumerate(). يمكنك قراءة درس:
شرح دالة enumerate في Python ولماذا تسهّل التعامل مع القوائم.
الفرق بين zip و enumerate
قد يخلط بعض المبتدئين بين zip() و enumerate(). الفرق بسيط:
zip()تُستخدم للمرور على أكثر من قائمة في نفس الوقت.enumerate()تُستخدم للحصول على الفهرس والقيمة من قائمة واحدة.
names = ["Ali", "Sara", "Omar"]
for index, name in enumerate(names):
print(index, name)
أما إذا كانت لديك قائمتان:
names = ["Ali", "Sara", "Omar"]
scores = [90, 85, 77]
for name, score in zip(names, scores):
print(name, score)
أخطاء شائعة عند استخدام zip
1. نسيان تحويل النتيجة إلى list
إذا كتبت:
print(zip([1, 2], ["A", "B"]))
فلن ترى العناصر مباشرة. استخدم:
print(list(zip([1, 2], ["A", "B"])))
2. عدم الانتباه لاختلاف طول القوائم
دالة zip() تتوقف عند أقصر قائمة، لذلك قد تفقد بعض العناصر إذا لم تكن منتبهًا.
3. استخدام zip في حالة لا تحتاجها
إذا كنت تتعامل مع قائمة واحدة فقط، لا تحتاج zip(). استخدم حلقة for عادية.
تمرين بسيط على دالة zip
جرّب كتابة برنامج يحتوي على قائمتين:
- قائمة أسماء المنتجات.
- قائمة أسعار المنتجات.
ثم استخدم zip() لطباعة كل منتج مع سعره.
مثال متوقع للناتج:
Keyboard : 25
Mouse : 10
Monitor : 120
الحل المقترح:
products = ["Keyboard", "Mouse", "Monitor"]
prices = [25, 10, 120]
for product, price in zip(products, prices):
print(product, ":", price)
مصادر رسمية للتوسع
للتفاصيل المرجعية راجع توثيق Python الرسمي لدالة zip. وإذا كنت تحتاج إلى الاحتفاظ بالعناصر الزائدة عند اختلاف الأطوال، فراجع توثيق itertools.zip_longest.
الخلاصة
دالة zip() من الدوال البسيطة والمهمة في Python، وتفيدك عندما تريد دمج عناصر متقابلة من قائمتين أو أكثر.
استخدامها يجعل الكود أوضح من الاعتماد على الفهارس، خصوصًا في الأمثلة التي تحتوي على أسماء ودرجات، مفاتيح وقيم، منتجات وأسعار، أو أي بيانات مترابطة.
تذكّر أن zip() تُرجع كائنًا قابلًا للتكرار، لذلك قد تحتاج إلى تحويل النتيجة إلى list أو dict حسب حاجتك.
وتذكّر أيضًا أنها تتوقف عند أقصر قائمة إذا كانت القوائم غير متساوية في الطول.
أسئلة شائعة مع إجاباتها
ما فائدة zip في Python؟
تُستخدم zip() لدمج العناصر المتقابلة من أكثر من قائمة أو كائن قابل للتكرار، مما يجعل التكرار على البيانات المرتبطة أسهل وأوضح.
هل zip ترجع List مباشرة؟
لا. دالة zip() ترجع كائنًا قابلًا للتكرار. إذا أردت عرض النتيجة كقائمة، استخدم list(zip(...)).
ماذا يحدث إذا كانت القوائم مختلفة الطول؟
تتوقف zip() عند أقصر قائمة، ولا تكمل مع العناصر الزائدة في القوائم الأطول.
هل يمكن تحويل zip إلى Dictionary؟
نعم. إذا كانت لديك قائمة مفاتيح وقائمة قيم، يمكنك استخدام dict(zip(keys, values)) لإنشاء قاموس بسهولة.
ما الفرق بين zip و enumerate؟
zip() تُستخدم للتكرار على أكثر من قائمة معًا، أما enumerate() فتُستخدم للحصول على الفهرس والقيمة من قائمة واحدة.
ما فائدة strict=True في zip؟
يُستخدم strict=True في Python 3.10 فأحدث عندما تتوقع أن تكون الـiterables متساوية في الطول. إذا اختلفت الأطوال، ترفع zip() خطأ ValueError بدل تجاهل العناصر الزائدة.
كيف أفك نتيجة zip إلى قائمتين؟
إذا كانت لديك أزواج مثل [("Ali", 90), ("Sara", 85)] فيمكنك استخدام names, scores = zip(*pairs). الناتج يكون tuples، ويمكن تحويل كل نتيجة إلى list عند الحاجة.




