البرمجة

استخدام *args و **kwargs في بايثون

كيفية استخدام *args و **kwargs في بايثون 3

عند العمل مع دوال بايثون، كثيراً ما نجد الحاجة إلى التعامل مع مجموعة من المعطيات التي قد تكون غير محددة مسبقًا. في هذه الحالة، تُعتبر الخصائص مثل *args و **kwargs من الأدوات الهامة التي تُسهل عملية تمرير عدد غير محدد من الوسائط إلى الدوال. على الرغم من أنهما يُستخدمان معًا في بعض الأحيان، إلا أن لكل منهما خصائصه واستخداماته المميزة. سنتناول في هذا المقال شرحاً مفصلاً حول كيفية استخدام *args و **kwargs في بايثون، بالإضافة إلى الفروق بينهما، وأمثلة عملية توضح كيفية الاستفادة منهما في تطوير التطبيقات البرمجية.

ما هو *args؟

في بايثون، تُستخدم *args لتمرير عدد غير محدد من الوسائط (المعطيات) إلى الدالة. يمكن استيعاب جميع هذه المعطيات في شكل “قائمة” داخل الدالة، مما يتيح لك التعامل مع عدد متغير من المعطيات دون الحاجة لتحديده مسبقًا في توقيع الدالة.

كيف تعمل *args؟

عند استخدام *args في الدالة، فإنه يسمح بتمرير أي عدد من الوسائط لها، بغض النظر عن عددها أو نوعها. فيما يلي مثال بسيط:

python
def add_numbers(*args): result = 0 for num in args: result += num return result print(add_numbers(1, 2, 3)) # ستطبع 6 print(add_numbers(5, 10)) # ستطبع 15 print(add_numbers(1, 2, 3, 4, 5)) # ستطبع 15

في المثال أعلاه، نرى أن الدالة add_numbers تقبل عدداً غير محدد من الأرقام، وتقوم بحساب مجموعها باستخدام حلقة for على جميع العناصر في args.

لماذا نستخدم *args؟

  • المرونة: يسمح لك باستخدام دوال تقبل عدد غير محدد من الوسائط.

  • تبسيط الكود: لا تحتاج إلى تحديد الوسائط مسبقًا، مما يجعل الكود أكثر مرونة وقوة.

  • الاستعمالات العامة: يمكن استخدامه عندما لا تعرف بالضبط عدد الوسائط التي سيتم تمريرها إلى الدالة.

ما هو **kwargs؟

على غرار *args، يتم استخدام **kwargs في بايثون لتمرير عدد غير محدد من الوسائط، ولكن مع اختلاف جوهري: **kwargs يُستخدم لتمرير الوسائط التي يتم تحديدها باستخدام الأسماء (المعلمات المسماة). بمعنى آخر، يتم تمرير المعطيات في صورة قاموس يحتوي على الأزواج (المفتاح، القيمة).

كيف تعمل **kwargs؟

عند استخدام **kwargs، يمكن للمطور تحديد المعطيات بشكل مسمى، أي أن كل معطى يأتي مع اسم محدد يمكن الوصول إليه داخل الدالة. مثال على ذلك:

python
def greet(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") greet(name="Ahmed", age=25, city="Cairo")

في هذا المثال، يتم تمرير المعطيات إلى الدالة greet في صورة قاموس، حيث يتم الوصول إلى كل معطى من خلال المفتاح (اسم المعطى).

لماذا نستخدم **kwargs؟

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

  • مناسبة للمشروعات الكبرى: في المشاريع الكبيرة التي تحتاج إلى التعامل مع العديد من المعطيات المسماة، يساعد **kwargs في تنظيم الكود.

الفرق بين *args و **kwargs

بينما يستخدم *args لتمرير عدد غير محدد من المعطيات غير المسماة (المعطيات العادية)، يستخدم **kwargs لتمرير عدد غير محدد من المعطيات المسماة (المعطيات مع الأسماء). فيما يلي مقارنة بينهما:

الخاصية *args **kwargs
النوع معطيات غير مسماة (عادة تكون قيمًا فقط) معطيات مسماة (مفتاح: قيمة)
الهيكل قائمة قاموس (Dictionary)
الاستخدام لتمرير قيم غير معروفة العدد إلى الدالة لتمرير معطيات مسماة إلى الدالة
الوصول الوصول بالترتيب (الفهرس) الوصول باستخدام المفاتيح

دمج *args مع **kwargs

من الممكن دمج كل من *args و **kwargs في دالة واحدة، مما يتيح لك تمرير مزيج من المعطيات غير المسماة والمسماة في نفس الوقت. في هذه الحالة، يتم تحديد *args أولًا، يليه **kwargs:

python
def display_info(*args, **kwargs): print("Positional arguments:", args) print("Keyword arguments:", kwargs) display_info(10, 20, name="Alice", age=30)

في هذا المثال، سيتم تمرير 10 و 20 كـ “معطيات موضعية” (Positional Arguments) إلى *args، بينما سيتم تمرير name="Alice" و age=30 كـ “معطيات مسماة” إلى **kwargs.

ملاحظات هامة عند دمج *args و **kwargs:

  • لا يمكن أن يتبع *args في توقيع الدالة أي معطيات مسماة غير معروفة العدد قبل **kwargs.

  • عند دمجها، يتم تمرير المعطيات الموضعية أولًا، ثم المعطيات المسماة.

مثال عملي على الاستخدام

في التطبيقات الواقعية، يمكنك استخدام *args و **kwargs لتطوير دوال أكثر تعقيدًا. على سبيل المثال، إذا كنت تبني دالة لإجراء عملية جمع للأرقام ولكنك تريد أيضًا تخصيص طريقة الجمع بناءً على معطى مسمى:

python
def custom_sum(*args, **kwargs): total = sum(args) if kwargs.get("multiply_by"): total *= kwargs["multiply_by"] return total print(custom_sum(1, 2, 3)) # ستطبع 6 print(custom_sum(1, 2, 3, multiply_by=2)) # ستطبع 12

في هذا المثال، يتم استخدام *args لحساب مجموع الأرقام، بينما يتيح **kwargs تطبيق عملية ضرب على المجموع إذا تم تمرير معطى multiply_by.

*args و **kwargs في التوارث (Inheritance)

عند العمل مع الوراثة في بايثون، قد تحتاج إلى استخدام *args و **kwargs لتمرير المعطيات بين الكائنات (objects) أو الفئات (classes) الموروثة. على سبيل المثال:

python
class Parent: def __init__(self, *args, **kwargs): print("Parent constructor") print("Args:", args) print("Kwargs:", kwargs) class Child(Parent): def __init__(self, *args, **kwargs): print("Child constructor") super().__init__(*args, **kwargs) child = Child(1, 2, 3, name="Alice", age=25)

في هذا المثال، يستخدم كل من *args و **kwargs لتمرير المعطيات إلى الكائن الأب (Parent class) من الكائن الابن (Child class).

ملاحظات ختامية

  • يمكن لـ *args و **kwargs جعل كودك أكثر مرونة وإعادة استخدامه بسهولة أكبر.

  • استخدام *args يسمح بتمرير معطيات غير محددة، بينما يتيح لك **kwargs تمرير معطيات مسماة.

  • يتم استخدام *args أولًا في الدالة، تليه **kwargs.

  • يمكن دمج كلاهما في دالة واحدة لتحقيق أقصى قدر من المرونة في تمرير المعطيات.

إن فهم آلية عمل *args و **kwargs يعد خطوة هامة في تعلم بايثون، حيث يساعدك على كتابة دوال مرنة وقوية تتعامل مع جميع أنواع المدخلات.