ملاحظة: هذا المقال بقلم أحمد بوشفرة. الآراء الواردة تعبر عن الكاتب.
أحمد بوشفرة: مبرمج ومؤلف تقني، أساعد المطورين على بناء تطبيقات ويب حديثة وسريعة.
يمكنك أيضاً نشر مقالك هنا والترويج لخدماتك أمام جمهور من المبرمجين. تواصل معنا
لخص هذا المقال باستخدام ChatGPT
انسخ الأمر أدناه والصقه في ChatGPT للحصول على ملخص سريع للمقال:
لخص لي هذا المقال في نقاط رئيسية: https://www.ahmedbouchefra.com/python-unpacking-secrets/
تم النسخ!
تخيل أنك تستطيع فك عناصر قائمة كاملة بسطر واحد. أو استقبال أكثر من قيمة من دالة بدون تعقيد. أو حتى دمج عدة قوائم أو قواميس معًا بضغطة “نجمة”.
هذا هو سحر تفكيك العناصر (Unpacking) في بايثون.
في هذا المقال، سنغوص في هذا المفهوم من الصفر إلى الاحتراف.
mindmap
root((تفكيك العناصر Unpacking))
::icon(fa fa-star)
القوائم (Lists)
::icon(fa fa-list)
توزيع على متغيرات
تجميع الباقي بـ *
دمج القوائم
تمرير للدوال
القواميس (Dictionaries)
::icon(fa fa-book)
تفكيك بـ **
دمج القواميس
تمرير للدوال
حالات استخدام
::icon(fa fa-cogs)
تبديل المتغيرات
حلقات التكرار For
ما هو تفكيك العناصر؟
ببساطة، هو تفكيك عناصر حاوية (مثل قائمة) وتوزيعها على متغيرات متعددة.
لنفترض أن لدينا قائمة أرقام.
numbers = [10, 20, 30]
يمكننا تفكيكها وتعيين كل عنصر لمتغير منفصل.
a, b, c = numbers
print(f"a: {a}") # سيطبع 10
print(f"b: {b}") # سيطبع 20
print(f"c: {c}") # سيطبع 30
بايثون ذكي كفاية ليعرف أن a يجب أن تأخذ القيمة الأولى، و b الثانية، وهكذا.
[!WARNING] شرط أساسي: يجب أن يكون عدد المتغيرات على اليسار مساويًا تمامًا لعدد العناصر في القائمة على اليمين، وإلا ستحصل على خطأ.
هذا ينطبق على أي نوع من التسلسلات، مثل الـ tuples.
point = (5, 8)
x, y = point
print(f"x: {x}") # سيطبع 5
print(f"y: {y}") # سيطبع 8
تجاهل بعض القيم
ماذا لو كنت تهتم فقط بقيم معينة وتريد تجاهل الباقي؟
يمكنك استخدام الشرطة السفلية _ كاسم للمتغير الذي تريد تجاهله.
هذه مجرد اصطلاح برمجي، لكنه يجعل الكود أوضح.
scores = [100, 200, 300]
# أريد فقط القيمة الأولى والأخيرة
first, _, last = scores
print(f"First: {first}") # سيطبع 100
print(f"Last: {last}") # سيطبع 300
هنا، لم نعد نهتم بالقيمة الوسطى (200)، لذلك تجاهلناها باستخدام _.
قوة النجمة *: تجميع الباقي
هنا يبدأ السحر الحقيقي. ماذا لو كان لديك عدد غير محدد من العناصر في قائمة؟
النجمة * تسمح لك بتجميع “بقية” العناصر في قائمة جديدة.
numbers = [1, 2, 3, 4, 5]
# خذ العنصر الأول، واجمع الباقي في قائمة جديدة
first, *rest = numbers
print(f"First: {first}") # سيطبع 1
print(f"Rest: {rest}") # سيطبع [2, 3, 4, 5]
النجمة * جمعت كل العناصر المتبقية في قائمة اسمها rest.
يمكنك أيضًا استخدامها للحصول على العناصر في المنتصف.
numbers = [1, 2, 3, 4, 5]
first, *middle, last = numbers
print(f"First: {first}") # سيطبع 1
print(f"Middle: {middle}") # سيطبع [2, 3, 4]
print(f"Last: {last}") # سيطبع 5
[!TIP] هذه الطريقة فعالة جدًا عندما تريد معالجة العنصر الأول والأخير بشكل مختلف عن بقية العناصر. النجمة
*تجمع كل ما تبقى في المنتصف.
تفكيك العناصر عند استدعاء الدوال
لنفترض أن لديك دالة تجمع ثلاثة أرقام.
def add(a, b, c):
return a + b + c
ولديك قائمة تحتوي على ثلاثة أرقام.
numbers_list = [10, 20, 30]
إذا حاولت تمرير القائمة مباشرة، ستحصل على خطأ.
لأن الدالة تتوقع ثلاثة وسائط منفصلة (a, b, c)، لكنها استلمت وسيطًا واحدًا فقط (القائمة numbers_list).
هنا يأتي دور النجمة * مرة أخرى.
إنها تفكك القائمة إلى عناصر فردية وتمررها كوسائط منفصلة للدالة.
# النجمة تفكك القائمة إلى 10, 20, 30
result = add(*numbers_list)
print(result) # سيطبع 60
النجمة هنا قامت بتفكيك القائمة [10, 20, 30] إلى add(10, 20, 30).
حالة خاصة: القواميس (Dictionaries) والنجمتان **
القواميس لها حالة خاصة لأنها تحتوي على مفتاح وقيمة.
لذلك، تحتاج إلى نجمتين ** لتفكيكها.
لنفترض أن لدينا دالة تطبع معلومات طالب.
def print_student_info(name, age):
print(f"الاسم: {name}, العمر: {age}")
وقاموس يحتوي على بيانات الطالب.
student_data = {"name": "علي", "age": 20}
لتمرير هذا القاموس للدالة، نستخدم **.
# النجمتان تفكك القاموس إلى وسائط مفتاحية
# name="علي", age=20
print_student_info(**student_data)
النتيجة ستكون: الاسم: علي, العمر: 20.
[!NOTE] فكر في الأمر كأن لديك مسبحة (القاموس). استخدام
**يقطع خيط المسبحة، فتتبعثر حباتها (المفاتيح والقيم)، مما يسمح للدالة بالتقاط كل حبة (قيمة) تحتاجها. بدون**، القاموس قطعة واحدة غير قابلة للتمرير بهذه الطريقة.
دمج القوائم والقواميس
يمكن استخدام التفكيك لدمج الحاويات بطريقة أنيقة.
دمج قائمتين
list1 = [1, 2]
list2 = [3, 4]
# فكك كل قائمة في قائمة جديدة
merged_list = [*list1, *list2]
print(merged_list) # سيطبع [1, 2, 3, 4]
بدون النجوم، كنت ستحصل على قائمة متداخلة: [[1, 2], [3, 4]].
دمج قاموسين
نفس المبدأ ينطبق على القواميس، ولكن باستخدام **.
dict1 = {"a": 1}
dict2 = {"b": 2}
merged_dict = {**dict1, **dict2}
print(merged_dict) # سيطبع {'a': 1, 'b': 2}
إذا كان هناك مفتاح مكرر، فإن قيمة القاموس الأخير هي التي ستُعتمد.
حيل إضافية مع التفكيك
تبديل قيم المتغيرات
طريقة بايثون الأنيقة لتبديل قيم متغيرين.
a = 5
b = 10
# تبديل القيم
a, b = b, a
print(f"a: {a}") # سيطبع 10
print(f"b: {b}") # سيطبع 5
التفكيك في حلقات التكرار
إذا كان لديك قائمة من الثنائيات (tuples)، يمكنك تفكيكها مباشرة في حلقة for.
pairs = [(1, 2), (3, 4), (5, 6)]
# فكك كل ثنائية إلى x و y
for x, y in pairs:
print(f"{x} + {y} = {x + y}")
النتيجة:
1 + 2 = 3
3 + 4 = 7
5 + 6 = 11
خلاصة
لقد تعلمنا أساسيات تفكيك العناصر:
- تفكيك القوائم لتوزيع القيم على متغيرات.
- استخدام النجمة
*لتجميع العناصر المتبقية أو لدمج القوائم أو لتمريرها كوسائط للدوال. - استخدام النجمتين
**لتفكيك القواميس وتمريرها كوسائط مفتاحية أو لدمجها.
استخدام هذه التقنيات يجعل كودك أكثر نظافة واحترافية وقابلية للقراءة. في المقالات القادمة، سنتناول أمثلة أكثر تعقيدًا واحترافية.
هل لديك سؤال أو استفسار؟ اترك تعليقاً بالأسفل: