سطح مقدماتی (Beginner Level)
در بسیاری از مواقع، هنگام تعریف یک تابع، دقیقاً نمیدانیم کاربر قرار است چند آرگومان به آن پاس دهد. برای مثال، تابعی که قرار است اعداد را جمع کند، ممکن است ۲ عدد بگیرد یا ۱۰۰ عدد. پایتون با استفاده از *args و **kwargs این مشکل را حل میکند.
۱. مفهوم *args (آرگومانهای موقعیتی نامحدود)
عبارت *args به تابع اجازه میدهد که هر تعداد آرگومان موقعیتی (Positional Arguments) را دریافت کند. پایتون این آرگومانها را در قالب یک تاپل (Tuple) ذخیره میکند.
نکته: نام
argsقراردادی است و میتوانید از هر نامی استفاده کنید، اما*(ستاره) الزامی است.
مثال ۱: جمع اعداد نامشخص (قابل اجرا)
در این مثال، تابع هر تعداد عددی که دریافت کند را با هم جمع میزند.
مثال ۲: ترکیب ورودی ثابت و متغیر
شما میتوانید آرگومانهای معمولی را با *args ترکیب کنید. آرگومانهای معمولی باید اول بیایند.
۲. مفهوم **kwargs (آرگومانهای کلیدواژهای نامحدود)
عبارت **kwargs (مخفف Keyword Arguments) به تابع اجازه میدهد هر تعداد آرگومان را به صورت کلید=مقدار (key=value) دریافت کند. این دادهها در قالب یک دیکشنری (Dictionary) ذخیره میشوند.
نکته: دو ستاره
**برای تشخیص این حالت الزامی است.
مثال: ساخت پروفایل کاربر
سطح پیشرفته (Professional Level)
در سطح حرفهای، بحث فقط دریافت ورودی نیست؛ بلکه بحث Unpacking (باز کردن) دادهها هنگام فراخوانی توابع و استفاده در الگوهای پیشرفته مثل ارثبری و دکوریتورهاست.
۱. آنپک کردن آرگومانها (Argument Unpacking)
اگر دادههای شما قبلاً داخل یک لیست یا دیکشنری باشند، نمیتوانید آنها را مستقیماً به تابعی که ورودیهای جداگانه میخواهد بدهید. باید از * و ** در زمان فراخوانی (Calling) استفاده کنید.
۲. ترتیب صحیح پارامترها (The Order of Parameters)
رعایت ترتیب در پایتون حیاتی است. اگر همه انواع آرگومانها را داشته باشید، ترتیب باید دقیقاً به این صورت باشد:
- Standard arguments
*args- Default arguments (گاهی قبل از args هم دیده میشود اما بعد از args رایجتر است برای Keyword-only)
**kwargs
یک الگوی رایج برای اجبار کردن کاربر به استفاده از آرگومانهای کلیدواژهای (Keyword-Only Arguments)، استفاده از * خالی است.
# Static code (Example of definition)
def forceful_function(name, *, mode="default", verbose=False):
# بعد از *، کاربر مجبور است نام پارامترها (mode و verbose) را بنویسد
pass
# forceful_function("Ali", "turbo", True) <-- ERROR
# forceful_function("Ali", mode="turbo", verbose=True) <-- OK
۳. فوروارد کردن آرگومانها (Argument Forwarding)
یکی از مهمترین کاربردهای *args و **kwargs در Wrapper ها و متد super() در کلاسهاست، جایی که میخواهیم آرگومانها را دستنخورده به تابع یا کلاس والد پاس دهیم.
۴. تایپ هینتینگ (Type Hinting)
در تایپ هینتینگ مدرن پایتون، وقتی برای *args تایپ مشخص میکنید، منظور تایپ تکتک اعضا است، نه کل تاپل.
# Static code (Type Hinting)
from typing import Any
# یعنی تمام ورودیهای args باید int باشند
def process_numbers(*args: int) -> int:
return sum(args)
# یعنی مقادیر دیکشنری kwargs باید رشته باشند (کلیدها همیشه رشتهاند)
def process_data(**kwargs: str) -> None:
pass