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


محمد الميداوي

تعدُّ المعاملات في تعاريف الدوال كيانات مسماة تُحدِّد وسيطًا (argument) يمكن أن يُمرَّر إلى الدالة المُعرَّفة.

أثناء البرمجة، قد لا تدرك جميع حالات الاستخدام الممكنة للشيفرة، لذا قد ترغب في توسيع خيارات المبرمجين المستقبليين الذين سيستخدمون الوحدة التي طورتها.

سنتعلم في هذا الدرس كيفيَّة تمرير عدد متغير من الوسائط إلى دالة ما باستخدام الصياغتين ‎*args‎ و ‎**kwargs‎.

كـيـفـيـــة-اسـتـخــــدام-args-و-kwargs.jpg

الوسيط ‎*args

في بايثون، يمكن استخدام الشكل أحادي النجمة ‎*args‎ كمعامل لتمرير قائمة غير محددة الطول من الوسائط غير المسماة (non-keyworded argument) إلى الدوال. تجدر الإشارة إلى أنّ النجمة (‎*‎) عنصر ضروري هنا، إذ رغم أنّ الكلمة ‎args‎ متعارف عليها بين المبرمجين، إلا أنها غير رسمية.

لنلقِ نظرة على مثال لدالة تستخدم وسيطين:

def multiply(x, y):
    print (x * y)

عرّفنا في الشفرة أعلاه دالة تقبل وسيطين ‎x‎ و ‎y‎، عندما نستدعي هذه الدالة، سنحتاج إلى تمرير عددين موافقين للوسيطين ‎x‎ و ‎y‎. في هذا المثال، سنمرّر العدد الصحيح ‎5‎ إلى ‎x‎، والعدد الصحيح ‎4‎ إلى ‎y‎:

def multiply(x, y):
    print (x * y)

multiply(5, 4)

عند تنفيذ الشفرة أعلاه:

python lets_multiply.py

سنحصل على المخرجات التالية:

20

ماذا لو قررنا لاحقًا أننا نود حساب ناتج ضرب ثلاثة أعداد بدلًا من عددين فقط؟ إذا حاولت تمرير عدد إضافي إلى الدالة، كما هو موضح أدناه:

def multiply(x, y):
    print (x * y)

multiply(5, 4, 3)

فسيُطلَق الخطأ التالي:

TypeError: multiply() takes 2 positional arguments but 3 were given

إذا شككت أنك ستحتاج إلى استخدام المزيد من الوسائط لاحقًا، فالحل هو استخدام ‎*args‎ كمعامل.

سنزيل المُعاملين ‎x‎ و ‎y‎ من الشفرة في المثال الأول، ونضع مكانهما ‎*args‎:

def multiply(*args):
    z = 1
    for num in args:
        z *= num
    print(z)

multiply(4, 5)
multiply(10, 9)
multiply(2, 3, 4)
multiply(3, 5, 10, 6)

عندما ننفّذ هذه الشفرة، سنحصل على ناتج استدعاءات الدالة أعلاه:

20
90
24
900

يمكننا باستخدام الوسيط ‎*args‎ تمرير أي عدد نحب من الوسائط عند استدعاء الدالة بالإضافة إلى كتابة شيفرة أكثر مرونة، وإنشاء دوال تقبل عددًا غير محدد مسبقًا من الوسائط غير المسماة.

الوسيط ‎**kwargs

يُستخدَم الشكل ذو النجمتين ‎**kwargs‎ لتمرير قاموس متغير الطول من الوسائط المسماة إلى الدالة المعرّفة. مرة أخرى، النجمتان (‎**‎) ضروريتان، فمع أنّ استخدام الكلمة ‎kwargs‎ متعارف عليه لدى المبرمجين، إلا أنها غير رسمية.

يمكن أن تأخذ ‎**kwargs‎، كما هو شأن ‎*args‎، أيّ عدد من الوسائط التي ترغب في تمريرها إلى الدالة بيْد أنّ ‎**kwargs‎ تختلف عن ‎*args‎ في أنها تستوجب تعيين أسماء المعاملات (keywords).

في المثال التالي، ستطبع الدالة الوسيط ‎**kwargs‎ الممرر إليها.

def print_kwargs(**kwargs):
        print(kwargs)

سنستدعي الآن الدالة ونمرر إليها بعض الوسائط المسماة:

def print_kwargs(**kwargs):
        print(kwargs)

print_kwargs(kwargs_1="Shark", kwargs_2=4.5, kwargs_3=True)

لننفذ البرنامج أعلاه:

python print_kwargs.py

سنحصل على المخرجات التالية:

{'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark'}

اعتمادًا على إصدار بايثون 3 الذي تستخدمه، فقد لا يكون القاموس مرتبًا. في بايثون 3.6 وما بعده، ستحصل على أزواج قيمة-مفتاح (key-value) مرتبة، ولكن في الإصدارات السابقة، سيكون ترتيب الأزواج عشوائيًا.

سيُنشَأ قاموس يسمى ‎kwargs‎، والذي يمكننا التعامل معه مثل أي قاموس عادي داخل الدالة.

لننشئ برنامجًا آخر لإظهار كيفية استخدام ‎**kwargs‎. سننشئ دالة تطبع قاموسًا من الأسماء. أولاً، سنبدأ بقاموس يحتوي اسمين:

def print_values(**kwargs):
    for key, value in kwargs.items():
        print("The value of {} is {}".format(key, value))

print_values(my_name="Sammy", your_name="Casey")

بعد تنفيذ البرنامج:

python print_values.py

سنحصل على مايلي:

The value of your_name is Casey
The value of my_name is Sammy

قد لا تكون القواميس مرتَّبة، لذلك قد يظهر الاسم ‎Casey‎ أولاً، وقد يظهر ثانيًا.

سنمرر الآن وسائط إضافية إلى الدالة لنرى كيف يمكن أن تقبل ‎**kwargs‎ أيّ عدد من الوسائط:

def print_values(**kwargs):
    for key, value in kwargs.items():
        print("The value of {} is {}".format(key, value))

print_values(
            name_1="Alex",
            name_2="Gray",
            name_3="Harper",
            name_4="Phoenix",
            name_5="Remy",
            name_6="Val"
        )

إذا نفّذنا البرنامج الآن، فسنحصل على المخرجات التالية، والتي قد تكون غير مرتبة:

The value of name_2 is Gray
The value of name_6 is Val
The value of name_4 is Phoenix
The value of name_5 is Remy
The value of name_3 is Harper
The value of name_1 is Alex

يتيح لك استخدام ‎**kwargs‎ مرونةً كبيرةً في استخدام الوسائط المسماة. فعند استخدامها، لن نحتاج إلى معرفة مسبقة بعدد الوسائط التي ستمرر إلى الدالة.

ترتيب الوسائط

عند الخلط بين عدة أنواع من الوسائط داخل دالة، أو داخل استدعاء دالة، يجب أن تظهر الوسائط وفق الترتيب التالي:

  • الوسائط العادية
  • ‎*args‎
  • الوسائط المسمّاة
  • ‎**kwargs‎

عمليًا، عند الجمع بين المعاملات العادية، والوسيطين ‎*args‎ و ‎**kwargs‎، فينبغي أن تكون وفق الترتيب التالي:

def example(arg_1, arg_2, *args, **kwargs):
...

وعند الجمع بين المعاملات العادية والمعاملات المسماة و ‎*args‎ و ‎**kwargs‎، ينبغي أن تكون وفق الترتيب التالي:

def example2(arg_1, arg_2, *args, kw_1="shark", kw_2="blobfish", **kwargs):
...

من المهم أن تأخذ في الحسبان ترتيب الوسائط عند إنشاء الدوال حتى لا تتسبب في إطلاق خطأٍ متعلقٍ بالصياغة.

استخدام ‎*args و ‎**kwargs في استدعاءات الدوال

يمكننا أيضًا استخدام ‎*args‎ و ‎**kwargs‎ لتمرير الوسائط إلى الدوال. أولاً، دعنا ننظر إلى مثال يستخدم ‎*args‎:

def some_args(arg_1, arg_2, arg_3):
    print("arg_1:", arg_1)
    print("arg_2:", arg_2)
    print("arg_3:", arg_3)

args = ("Sammy", "Casey", "Alex")
some_args(*args)

في الدالة أعلاه، هناك ثلاثة معاملات، وهي ‎arg_1‎ و ‎arg_‎ و ‎arg_3‎. ستطبع الدالة كل هذه الوسائط. بعد ذلك أنشأنا متغيرًا، وأَحلنا عليه عنصرًا تكراريًا (في هذه الحالة، صف)، ثم مرَّرنا ذلك المتغير إلى الدالة باستخدام الصياغة النجمية (asterisk syntax).

عندما ننفّذ البرنامج باستخدام الأمر ‎python some_args.py‎، سنحصل على المخرجات التالية:

arg_1: Sammy
arg_2: Casey
arg_3: Alex

يمكننا أيضًا تعديل البرنامج أعلاه، واستخدام قائمة. سندمج أيضًا ‎*args‎ مع وسيط مسمى:

def some_args(arg_1, arg_2, arg_3):
    print("arg_1:", arg_1)
    print("arg_2:", arg_2)
    print("arg_3:", arg_3)

my_list = [2, 3]
some_args(1, *my_list)

إذا نفذنا البرنامج أعلاه، فسنحصل على المخرجات التالية:

arg_1: 1
arg_2: 2
arg_3: 3

وبالمثل، يمكن استخدام الوسائط المسماة ‎**kwargs‎ لاستدعاء دالة.

سننشئ متغيرًا، ونسند إليه قاموسًا من 3 أزواج مفتاح-قيمة (سنستخدم ‎kwargs‎ هنا، ولكن يمكنك تسميته ما تشاء)، ثم نُمرِّره إلى دالة ذات 3 وسائط:

def some_kwargs(kwarg_1, kwarg_2, kwarg_3):
    print("kwarg_1:", kwarg_1)
    print("kwarg_2:", kwarg_2)
    print("kwarg_3:", kwarg_3)

kwargs = {"kwarg_1": "Val", "kwarg_2": "Harper", "kwarg_3": "Remy"}
some_kwargs(**kwargs)

عند تنفيذ البرنامج أعلاه باستخدام الأمر ‎python some_kwargs.py‎، سنحصل على المخرجات التالية:

kwarg_1: Val
kwarg_2: Harper
kwarg_3: Remy

خلاصة

يمكنك استخدام الصياغتين الخاصتين ‎*args‎ و ‎**kwargs‎ ضمن تَعاريف الدوال لتمرير أيّ عدد تشاء من الوسائط إليها.

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

هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3.

ترجمة -وبتصرّف- للمقال How To Use *args and **kwargs in Python 3 لصاحبته Lisa Tagliaferri

اقرأ أيضًا





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن