بسیاری اوقات پیش میآید که ما قصد فراخوانی تابعی را داریم و ورودیهای این تابع در یک لیست، چندتایی یا دیکشنری قرار دارند. ابتداییترین کار ممکن جداکردن تک تک عناصر و دادن آنها به عنوان ورودی به تابع است. ولی میتوان با استفاده از عملگرهای * و ** کار را سادهتر کرد. در این نوشته با نحوه استفاده از این عملگرها آشنا خواهیم شد.
بسم الله الرحمن الرحیم
همانگونه که گفته شد در این نوشته قصد داریم با نحوه استفاده از عناصر یک لیست یا دیکشنری به عنوان ورودیهای یک تابع آشنا شویم. برای این کار ابتدا تابعی را در نظر میگیریم که قصد فراخوانی آن با ورودیهای مشخصی را داریم:
def func(arg1, arg2, arg3): print('arg1 =', arg1) print('arg2 =', arg2) print('arg3 =', arg3)
در مرحله اول فرض میکنیم ورودیهای دلخواه ما به ترتیب در یک لیست یا چندتایی قرار دارند و میخواهیم بدون جداسازی دستی تک تک عناصر، تابع را با استفاده از آن فراخوانی کنیم. در این حالت میتوانیم لیست یا چندتایی را با یک * در ابتدای نام آن به عنوان ورودی تابع بدهیم و پایتون به طور خودکار عناصر را برای مقداردهی ورودیهای تابع بسط خواهد داد. مثال زیر را در ادامه تابعی که تعریف نمودیم مشاهده نمایید:
def func(arg1, arg2, arg3): print('arg1 =', arg1) print('arg2 =', arg2) print('arg3 =', arg3) l = ['one', 'two', 'three'] func(*l) print("------------") l = ('one', 'two', 'three') func(*l) print("------------")
همان طور که پیشبینی میشود، خروجی کد فوق به صورت زیر خواهد بود:
arg1 = one arg2 = two arg3 = three ------------ arg1 = one arg2 = two arg3 = three ------------
دقت نمایید، اگر در این نوع فراخوانی توابع تعداد عناصر لیست یا چندتایی با تعداد ورودیها برابر نباشد، پایتون خطای TypeError را صادر خواهد کرد.حال اگر ورودیهای تابع ما دارای مقداردهی پیشفرض باشند، مسئله کمی متفاوت خواهد بود. در این حالت تعداد عناصر حاضر در لیست یا چندتایی میتواند از تعداد متغیرها کمتر باشد. در این صورت پایتون به ترتیب تا جایی که عناصر موجود اجازه دهند متغیرهای ورودی تابع را مقداردهی خواهد کرد و مقدار پارامترهای باقیمانده، مقدار پیشفرض آنها خواهد بود. به مثال زیر دقت نمایید:
def func(arg1=1, arg2=2, arg3=3): print('arg1 =', arg1) print('arg2 =', arg2) print('arg3 =', arg3) l = ['one', 'two'] func(*l) print("------------") l = ['one'] func(*l) print("------------")
خروجی این قطعه کد به صورت زیر خواهد بود:
arg1 = one arg2 = two arg3 = 3 ------------ arg1 = one arg2 = 2 arg3 = 3 ------------
حال اگر تابعی که فراخوانی میگردد، تعداد ورودی متغیر داشته باشد، پایتون با استفاده از لیست یا چندتایی داده شده متغیرهای مشخص ابتدایی را مقداردهی کرده و باقی مقادیر را به ورودیهای آزاد اختصاص خواهد داد. مثال زیر را مشاهده نمایید:
def func_args(arg1, *args): print('arg1 =', arg1) print('args =', args) func_args(*['one', 'two']) print("---------------") func_args(*['one', 'two', 'three']) print("-----------------------") func_args(*['one', 'two', 'three', 'four']) print("-------------------------------")
خروجی این قطعه کد به صورت زیر خواهد بود:
arg1 = one args = ('two',) --------------- arg1 = one args = ('two', 'three') ----------------------- arg1 = one args = ('two', 'three', 'four') -------------------------------
در مرحله دوم ما قصد داریم از عناصر یک دیکشنری برای فراخوانی یک تابع استفاده کنیم. در این صورت اگر ما یک دیکشنری داشته باشیم که نام عناصر آن هم نام با متغیرهای ورودی یک تابع باشد، میتوانیم با قرار دادن ** در ابتدای نام آن هنگام فراخوانی تابع از آن استفاده کنیم. مثال زیر را در نظر بگیرید:
def func(arg1, arg2, arg3): print('arg1 =', arg1) print('arg2 =', arg2) print('arg3 =', arg3) d = {'arg1': 'one', 'arg2': 'two', 'arg3': 'three'} func(**d)
خروجی این قطعه کد به صورت زیر خواهد بود:
arg1 = one arg2 = two arg3 = three
دقت کنید، در صورتی که در دیکشنری نامی وجود داشته باشد که در زمره متغیرهای ورودی تابع نباشد، پایتون خطای TypeError را صادر خواهد نمود. همچنین هنگامی که متغیرهای ورودی تابع دارای مقدار پیشفرض باشند، هنگام فراخوانی تابع با استفاده از دیکشنری، در صورتی که برخی نامهای ورودی در دیکشنری وجود نداشته باشند، مشکلی پیش نیامده و برای آنها از مقدار پیشفرض استفاده خواهد شد. مقدار متناظر با نام متغیرهای ورودی موجود در دیکشنری نیز جایگزین مقدار پیشفرض شده و فراخوانی با آنها انجام خواهد گردید. مثال زیر این مسئله را نمایش میدهد:
def func_default(arg1=1, arg2=2, arg3=3): print('arg1 =', arg1) print('arg2 =', arg2) print('arg3 =', arg3) func_default(**{'arg1': 'one'}) print("----------") func_default(**{'arg2': 'two', 'arg3': 'three'}) print("------------")
خروجی این قطعه کد به صورت زیر خواهد بود:
arg1 = one arg2 = 2 arg3 = 3 ---------- arg1 = 1 arg2 = two arg3 = three ------------
در صورتی که تابع مورد نظر برای فراخوانی دارای متغیر با عناصر نامشخص باشد، ورودیهای مشخص تابع از طریق دیکشنری مقداردهی خواهند گردید و باقی عناصر دیکشنری به عنوان ورودی دارای عناصر نامشخص داده خواهند شد. مثال زیر این موضوع را به روشنی بیان میکند:
def func_kwargs(arg1, **kwargs): print('arg1 =', arg1) print('kwargs =', kwargs) func_kwargs(**{'arg1': 'one', 'arg2': 'two', 'arg3': 'three'}) print("-----------------------------------------") func_kwargs(**{'arg1': 'one', 'arg2': 'two', 'arg3': 'three', 'arg4': 'four'}) print("---------------------------------------------------------") func_kwargs(**{'arg1': 'one', 'arg3': 'three'}) print("--------------------------")
در نهایت خروجی این قطعه کد نیز به صورت زیر خواهد بود:
arg1 = one kwargs = {'arg2': 'two', 'arg3': 'three'} ----------------------------------------- arg1 = one kwargs = {'arg2': 'two', 'arg3': 'three', 'arg4': 'four'} --------------------------------------------------------- arg1 = one kwargs = {'arg3': 'three'} --------------------------