FA-TOOLS — Header Component
آموزش args و kwargs در پایتون با مثال کاربردی

آموزش args و kwargs در پایتون با مثال کاربردی

سلام رفیق برنامه‌نویس! اگه مدت زیادیه که با پایتون سروکله می‌زنی یا حتی تازه‌کاری و دنبال راه‌هایی هستی که کدنویسیت رو حرفه‌ای‌تر و انعطاف‌پذیرتر کنی، احتمالاً اسم `*args` و `**kwargs` به گوشت خورده. این دوتا، ابزارهای جادویی پایتون هستن که به تو اجازه می‌دن توابع بسیار قدرتمند و همه‌کاره بنویسی که بتونن با تعداد متغیری از ورودی‌ها کار کنن. دیگه لازم نیست برای هر تعداد ورودی، تابع جدیدی تعریف کنی. قراره اینجا یه سفر عمیق به دنیای این دو مفهوم داشته باشیم و با مثال‌های کاربردی، تمام زوایاشون رو کشف کنیم تا بتونی تو پروژه‌هات حسابی ازشون بهره ببری و کدت تمیزتر و پویاتر بشه.

قبل از اینکه شیرجه بزنیم تو کدها، یه پیشنهاد دوستانه: اگه دنبال ابزارهای پایتونی درجه یک برای سرعت بخشیدن به کارات هستی یا می‌خوای بهترین اسنیپت‌های CSS، JS و HTML رو دم دستت داشته باشی، حتماً یه سری به فروشگاه ابزارهای برنامه‌نویسی fa-tools.ir بزن! اونجا یه عالمه کد و ابزار کاربردی هست که مطمئنم به کارت میاد.

📞 سوالی داری؟ مستقیم با ما تماس بگیر: 09202232789

✨ نقشه راه سریع: args و kwargs در یک نگاه ✨

⭐ *args (آرگومان‌های متغییر موقعیتی)

  • برای گرفتن تعداد نامشخصی از آرگومان‌های بدون نام (موقعیتی).
  • آرگومان‌ها را به صورت یک تاپل (tuple) جمع‌آوری می‌کند.
  • ترتیب آرگومان‌ها بسیار مهم است!
  • 💡 مثال تعریف: def func(*items):
  • 🚀 مثال فراخوانی: func(1, 'سلام', True)

🚀 **kwargs (آرگومان‌های متغییر کلیدواژه‌ای)

  • برای گرفتن تعداد نامشخصی از آرگومان‌های نام‌گذاری شده (کلیدواژه‌ای).
  • آرگومان‌ها را به صورت یک دیکشنری (dictionary) جمع‌آوری می‌کند.
  • ترتیب آرگومان‌ها مهم نیست، اما کلیدها مهمند!
  • 💡 مثال تعریف: def func(**data):
  • 🚀 مثال فراخوانی: func(نام='علی', سن=30)

🧠 نکته طلایی: ترکیب هر دو!

همیشه `*args` قبل از `**kwargs` در تعریف تابع می‌آید.
ساختار استاندارد: def func(arg1, *args, **kwargs):

این ابزارها بهت کمک می‌کنن تا توابعی انعطاف‌پذیر و قدرتمند بسازی که نیازهای مختلف رو برسی کنن.

*args چیست؟ (آرگومان‌های متغییر موقعیتی)

آموزش args و kwargs در پایتون با مثال کاربردی — تصویر 1

فرض کن یه تابعی می‌خوای بنویسی که بتونه هر تعداد عددی رو که بهش می‌دی با هم جمع کنه. شاید امروز سه تا عدد بدی، فردا پنج تا و پس‌فردا ده تا. اگه بخوای برای هر تعداد ورودی یه تابع جدا بنویسی، کدت خیلی شلوغ و غیرقابل مدیریت می‌شه. اینجا `*args` مثل یه قهرمان وارد میدون می‌شه.

وقتی تو تعریف یه تابع از *args استفاده می‌کنی، به پایتون می‌گی که این تابع می‌تونه تعداد دلخواهی از آرگومان‌های موقعیتی (positional arguments) رو بپذیره. پایتون هم باهوشه و تمام اون آرگومان‌ها رو جمع‌آوری می‌کنه و به صورت یه تاپل (tuple) در میاره که می‌تونی داخل تابع ازش استفاده کنی. اسم args یک قرارداده، می‌تونی هر اسمی بذاری (مثلاً *numbers)، اما args متداول‌ترین و خواناترین روشه.

چرا از *args استفاده کنیم؟

  • انعطاف‌پذیری بالا: تابعی می‌نویسی که می‌تونه با هر تعداد ورودی کار کنه، بدون اینکه نیاز به تغییر تابع داشته باشی.
  • کد تمیزتر: از تکرار کد (boilerplate code) جلوگیری می‌کنه و تابعت رو خواناتر می‌کنه.
  • ابزاری برای جمع‌آوری: آرگومان‌های ارسالی رو به صورت یه مجموعه قابل پیمایش (تاپل) در اختیارت می‌ذاره.
  • فراخوانی توابع: برای پاس دادن یک لیست یا تاپل از آرگومان‌ها به تابعی که انتظار آرگومان‌های جداگانه داره، استفاده می‌شه. (این رو جلوتر توضیح می‌دم).

مثال‌های کاربردی با *args

مثال 1: جمع کردن هر تعداد عدد


def جمع_اعداد(*اعداد):
    مجموع = 0
    for عدد in اعداد:
        مجموع += عدد
    return مجموع

print(جمع_اعداد(1, 2, 3))  # خروجی: 6
print(جمع_اعداد(10, 20, 30, 40))  # خروجی: 100
print(جمع_اعداد())  # خروجی: 0 (تاپل خالی)
    

همونطور که می‌بینی، با استفاده از *اعداد، تابع جمع_اعداد تونسته هر تعداد آرگومان رو بپذیره و اون‌ها رو به صورت یه تاپل به اسم اعداد ذخیره کنه.

مثال 2: نمایش پیام‌های مختلف


def نمایش_پیام‌ها(*پیام‌ها):
    print("--- شروع پیام‌ها ---")
    for پیام in پیام‌ها:
        print(پیام)
    print("--- پایان پیام‌ها ---")

نمایش_پیام‌ها("سلام", "خوش اومدی")
# خروجی:
# --- شروع پیام‌ها ---
# سلام
# خوش اومدی
# --- پایان پیام‌ها ---

نمایش_پیام‌ها("این یک پیام طولانی است.", "یک پیام دیگر.", 123, True)
# خروجی:
# --- شروع پیام‌ها ---
# این یک پیام طولانی است.
# یک پیام دیگر.
# 123
# True
# --- پایان پیام‌ها ---
    

این تابع هر نوع داده‌ای رو به عنوان پیام می‌پذیره و نشون می‌ده. این انعطاف‌پذیری کار رو برای ما خیلی راحت‌تر می‌کنه. در واقع شما با این روش دارید به توابع پایتون قابلیت پویا بودن و پاسخگو بودن به نیاز‌های مختلف رو می‌دید. برای یادگیری بیشتر در مورد اسنیپت‌های پایتون، می‌تونی به بخش اسنیپت‌های پایتون در سایت ما مراجعه کنی.

**kwargs چیست؟ (آرگومان‌های متغییر کلیدواژه‌ای)

آموزش args و kwargs در پایتون با مثال کاربردی — تصویر 2

حالا فرض کن می‌خوای یه تابع بنویسی که اطلاعات یک کاربر رو دریافت کنه. این اطلاعات می‌تونه شامل نام، سن، ایمیل، شهر و هر چیز دیگه‌ای باشه. بعضی وقتا فقط نام و سن لازمه، بعضی وقتا همه اطلاعات. اینجا `**kwargs` به کمکت می‌آد.

نماد **kwargs در تعریف تابع به پایتون می‌گه که این تابع می‌تونه تعداد دلخواهی از آرگومان‌های کلیدواژه‌ای (keyword arguments) رو بپذیره. پایتون تمام این آرگومان‌های نام‌گذاری شده رو جمع‌آوری می‌کنه و اون‌ها رو به صورت یه دیکشنری (dictionary) در میاره. هر کلید در دیکشنری، همون نام آرگومان و هر مقدار، همون مقدار آرگومان خواهد بود. مثل *args، اسم kwargs هم قرارداده، و می‌تونی از اسامی دیگه‌ای مثل **data استفاده کنی.

مزایای استفاده از **kwargs

  • ورودی‌های اختیاری: به راحتی می‌تونی توابعی بنویسی که ورودی‌های اختیاری داشته باشن.
  • خوانایی بهتر: چون آرگومان‌ها نام‌گذاری شده هستن، کدت خواناتر می‌شه و می‌فهمی هر مقدار برای چیه.
  • پاس دادن دیکشنری: می‌تونی یک دیکشنری از داده‌ها رو به تابعی که انتظار آرگومان‌های کلیدواژه‌ای رو داره، پاس بدی.
  • طراحی API انعطاف‌پذیر: برای ساخت APIها و کتابخانه‌هایی که نیاز به ورودی‌های پیکربندی مختلف دارن، عالیه.

مثال‌های کاربردی با **kwargs

مثال 1: نمایش اطلاعات کاربر


def نمایش_مشخصات_کاربر(**مشخصات):
    print("--- مشخصات کاربر ---")
    if "نام" in مشخصات:
        print(f"نام: {مشخصات['نام']}")
    if "سن" in مشخصات:
        print(f"سن: {مشخصات['سن']}")
    if "شهر" in مشخصات:
        print(f"شهر: {مشخصات['شهر']}")
    if "پست_الکترونیک" in مشخصات:
        print(f"پست الکترونیک: {مشخصات['پست_الکترونیک']}")
    for کلید, مقدار in مشخصات.items():
        if کلید not in ["نام", "سن", "شهر", "پست_الکترونیک"]:
            print(f"{کلید.replace('_', ' ')}: {مقدار}")
    print("--- پایان مشخصات ---")

نمایش_مشخصات_کاربر(نام="سارا", سن=28)
# خروجی:
# --- مشخصات کاربر ---
# نام: سارا
# سن: 28
# --- پایان مشخصات ---

نمایش_مشخصات_کاربر(نام="امیر", شهر="تهران", شغل="برنامه‌نویس")
# خروجی:
# --- مشخصات کاربر ---
# نام: امیر
# شهر: تهران
# شغل: برنامه‌نویس
# --- پایان مشخصات ---
    

این تابع با استفاده از **مشخصات، هر تعداد آرگومان کلیدواژه‌ای را به صورت یک دیکشنری به نام مشخصات دریافت می‌کنه و تمام آنها را به ما نمایش می‌ده. برای مدیریت بهتر اسنیپت‌های CSS و HTML هم، می‌تونی سری به این لینک‌ها بزنی: اسنیپت‌های CSS و اسنیپت‌های HTML.

مثال 2: تنظیمات یک ابزار


def اعمال_تنظیمات(**تنظیمات):
    print("اعمال تنظیمات...")
    for کلید, مقدار in تنظیمات.items():
        print(f"- {کلید}: {مقدار}")
    print("تنظیمات با موفقیت اعمال شد.")

اعمال_تنظیمات(رنگ_زمینه="آبی", اندازه_فونت=14)
# خروجی:
# اعمال تنظیمات...
# - رنگ_زمینه: آبی
# - اندازه_فونت: 14
# تنظیمات با موفقیت اعمال شد.

اعمال_تنظیمات(مد_تاریک=True)
# خروجی:
# اعمال تنظیمات...
# - مد_تاریک: True
# تنظیمات با موفقیت اعمال شد.
    

ترکیب جادویی: *args و **kwargs با هم

آموزش args و kwargs در پایتون با مثال کاربردی — تصویر 3

حالا که با هر کدوم از این ستاره‌ها جداگانه آشنا شدیم، وقتشه که ببینیم چطور می‌تونیم اون‌ها رو با هم تو یه تابع استفاده کنیم. این ترکیب بهت اجازه می‌ده توابعی بنویسی که واقعاً همه‌کاره باشن و بتونن هر نوع ورودی رو بپذیرن، چه موقعیتی باشن و چه کلیدواژه‌ای.

قانون طلایی: وقتی *args و **kwargs رو در تعریف یک تابع با هم استفاده می‌کنی، `*args` همیشه باید قبل از `**kwargs` قرار بگیره. اگر آرگومان‌های معمولی (ثابت) هم داری، اون‌ها هم باید قبل از `*args` باشن. ترتیب درست به این صورته:

def my_function(fixed_arg, *args, **kwargs):

مثال ترکیب *args و **kwargs

تابع پردازش‌گر همه‌کاره


def پردازش_داده(شناسه_کاربری, *داده_موقعیتی, **داده_کلیدواژه‌ای):
    print(f"شناسه کاربری: {شناسه_کاربری}")

    if داده_موقعیتی:
        print("داده‌های موقعیتی:")
        for داده in داده_موقعیتی:
            print(f"- {داده}")
    else:
        print("هیچ داده موقعیتی وجود ندارد.")

    if داده_کلیدواژه‌ای:
        print("داده‌های کلیدواژه‌ای:")
        for کلید, مقدار in داده_کلیدواژه‌ای.items():
            print(f"- {کلید}: {مقدار}")
    else:
        print("هیچ داده کلیدواژه‌ای وجود ندارد.")

print("n--- سناریو 1: فقط آرگومان‌های موقعیتی ---")
پردازش_داده(123, "گزینه A", "گزینه B")
# خروجی:
# --- سناریو 1: فقط آرگومان‌های موقعیتی ---
# شناسه کاربری: 123
# داده‌های موقعیتی:
# - گزینه A
# - گزینه B
# هیچ داده کلیدواژه‌ای وجود ندارد.

print("n--- سناریو 2: فقط آرگومان‌های کلیدواژه‌ای ---")
پردازش_داده(456, حالت="فعال", سطح="بالا")
# خروجی:
# --- سناریو 2: فقط آرگومان‌های کلیدواژه‌ای ---
# شناسه کاربری: 456
# هیچ داده موقعیتی وجود ندارد.
# داده‌های کلیدواژه‌ای:
# - حالت: فعال
# - سطح: بالا

print("n--- سناریو 3: ترکیب هر دو ---")
پردازش_داده(789, "ورودی اول", 100, وضعیت="تایید شده", تعداد=5)
# خروجی:
# --- سناریو 3: ترکیب هر دو ---
# شناسه کاربری: 789
# داده‌های موقعیتی:
# - ورودی اول
# - 100
# داده‌های کلیدواژه‌ای:
# - وضعیت: تایید شده
# - تعداد: 5
    

این مثال به وضوح نشون می‌ده که چطور یک تابع واحد می‌تونه ورودی‌های متنوعی رو مدیریت کنه. آرگومان شناسه_کاربری یک آرگومان ثابت و اجباری است، *داده_موقعیتی تمام ورودی‌های بدون نام بعد از آن را جمع‌آوری می‌کند و **داده_کلیدواژه‌ای تمام ورودی‌های نام‌گذاری شده را.

قوانین مهم و بهترین روش‌ها

استفاده از *args و **kwargs قدرتمنده، اما مثل هر ابزار قدرتمند دیگه‌ای، نیاز به درک صحیح و استفاده درست داره تا کدت خوانا و قابل نگهداری بمونه.

  • ترتیب آرگومان‌ها: این مورد رو باید حتماً رعایت کنی. اگر هم آرگومان‌های معمولی (positional-only) و هم کلیدواژه‌ای (keyword-only) داری، ترتیب به این صورت خواهد بود:
    def func(positional_arg_1, positional_arg_2, *args, keyword_only_arg, **kwargs):

    positional_arg_1 و positional_arg_2 آرگومان‌های ثابت هستند. *args آرگومان‌های موقعیتی متغییر را می‌گیرد. keyword_only_arg یک آرگومان است که حتماً باید به صورت کلیدواژه‌ای (مثلاً keyword_only_arg=value) به تابع پاس داده شود. **kwargs هم آرگومان‌های کلیدواژه‌ای متغیر را جمع می‌کند. (البته استفاده از positional-only و keyword-only آرگومان‌ها با نماد / و * در پایتون ۳.۸ به بعد کمی متفاوت تعریف می‌شود.)

  • خوانایی: سعی کن نام args و kwargs رو تغییر ندی مگر اینکه واقعاً نام مناسب‌تری برای مفهوم خاصی داشته باشی (مثلاً *numbers یا **options).
  • زیاده‌روی نکن: همیشه از این قابلیت‌ها استفاده نکن. اگه می‌دونی تابعت ورودی‌های ثابتی داره، بهتره همون‌ها رو به صورت صریح تعریف کنی. این کار خوانایی رو بالا می‌بره و اشکال‌زدایی رو آسون‌تر می‌کنه.
  • مستندسازی (Docstrings): حتماً در Docstring تابعت توضیح بده که *args و **kwargs چه نوع ورودی‌هایی رو انتظار دارن.
  • گسترش آرگومان‌ها (Argument Unpacking): می‌تونی از * و ** برای “باز کردن” (unpacking) لیست‌ها/تاپل‌ها و دیکشنری‌ها هنگام فراخوانی تابع استفاده کنی. این موضوع در صفحه اسنیپت‌ها به طور کاملتر توضیح داده شده.

مثال: گسترش آرگومان‌ها (Unpacking)

استفاده از * و ** در هنگام فراخوانی تابع


def نمایش_اطلاعات(پیام_اصلی, *بقیه_پیام‌ها, **گزینه‌ها):
    print(f"پیام اصلی: {پیام_اصلی}")
    if بقیه_پیام‌ها:
        print(f"پیام‌های اضافی: {', '.join(map(str, بقیه_پیام‌ها))}")
    if گزینه‌ها:
        print("گزینه‌ها:")
        for کلید, مقدار in گزینه‌ها.items():
            print(f"- {کلید}: {مقدار}")

لیست_پیام‌ها = ["آیتم ۱", "آیتم ۲", "آیتم ۳"]
تنظیمات_اضافی = {"حالت": "تست", "ورژن": 1.0}

نمایش_اطلاعات("این پیغام اصلی است", *لیست_پیام‌ها, **تنظیمات_اضافی)
# خروجی:
# پیام اصلی: این پیغام اصلی است
# پیام‌های اضافی: آیتم ۱, آیتم ۲, آیتم ۳
# گزینه‌ها:
# - حالت: تست
# - ورژن: 1.0
    

در این مثال، *لیست_پیام‌ها باعث می‌شه آیتم‌های داخل لیست_پیام‌ها به عنوان آرگومان‌های جداگانه به *بقیه_پیام‌ها ارسال بشن، و **تنظیمات_اضافی هم کلید-مقدار‌های دیکشنری رو به **گزینه‌ها می‌فرسته. این یک الگو برای برنامه‌های مدیریت محتوا و حتی توسعه با وردپرس بسیار کاربردی است. می‌تونی برای دیدن اسنیپت‌های مرتبط با وردپرس به اینجا سر بزنی.

موارد استفاده پیشرفته و الگوهای طراحی

علاوه بر کاربردهای پایه‌ای که دیدیم، *args و **kwargs در الگوهای طراحی پیشرفته‌تر و ساختاردهی کد نقش مهمی دارن. اینجا به دو مورد از اون‌ها اشاره می‌کنیم.

1. Decorators (دکوراتورها)

دکوراتورها توابع یا کلاس‌هایی هستند که عملکرد توابع یا متدهای دیگه رو بدون تغییر کد اصلی اون‌ها، گسترش می‌دن. *args و **kwargs در اینجا برای اطمینان از اینکه دکوراتور می‌تونه با هر تابعی، با هر امضایی (signature)، کار کنه، ضروری هستن. این رویکرد رو تو توسعه با جاوااسکریپت و فریم‌ورک‌هایی مثل React هم می‌بینیم. اگر علاقه‌مند به این موضوع هستی، می‌تونی سری به اسنیپت‌های جاوااسکریپت بزنی.

مثال دکوراتور برای اندازه‌گیری زمان اجرا


import time

def زمان_اجرا(func):
    def wrapper(*args, **kwargs):
        شروع = time.time()
        نتیجه = func(*args, **kwargs)  # فراخوانی تابع اصلی با args و kwargs
        پایان = time.time()
        print(f"تابع {func.__name__} در {پایان - شروع:.4f} ثانیه اجرا شد.")
        return نتیجه
    return wrapper

@زمان_اجرا
def محاسبه_پیچیده(حد_بالا):
    sum_val = 0
    for i in range(حد_بالا):
        sum_val += i ** 2
    return sum_val

محاسبه_پیچیده(1000000)
# خروجی (زمان ممکن است متفاوت باشد):
# تابع محاسبه_پیچیده در 0.1601 ثانیه اجرا شد.
    

در اینجا، *args و **kwargs به تابع wrapper اجازه می‌دهند هر آرگومانی را که به محاسبه_پیچیده ارسال می‌شود، دریافت کرده و سپس به تابع اصلی (func) منتقل کنند.

2. Proxy Functions (توابع واسط)

گاهی اوقات نیاز داریم یک تابع بنویسیم که فقط وظیفه “رد کردن” (forwarding) تمام آرگومان‌ها به یک تابع یا متد دیگه رو بر عهده داره. این می‌تونه برای لاگ‌برداری، کنترل دسترسی، یا تغییر رفتار قبل/بعد از فراخوانی تابع اصلی مفید باشه.

مثال: تابع واسط برای لاگ‌برداری


def عملیات_اصلی(نام, مقدار=1):
    print(f"اجرای عملیات اصلی: نام={نام}, مقدار={مقدار}")
    return نام * مقدار

def تابع_واسط_لاگ(func, *args, **kwargs):
    print(f"لاگ: فراخوانی تابع {func.__name__} با args={args}, kwargs={kwargs}")
    نتیجه = func(*args, **kwargs)  # پاس دادن آرگومان‌ها
    print(f"لاگ: تابع {func.__name__} با نتیجه {نتیجه} به پایان رسید.")
    return نتیجه

تابع_واسط_لاگ(عملیات_اصلی, "A", مقدار=5)
# خروجی:
# لاگ: فراخوانی تابع عملیات_اصلی با args=('A',), kwargs={'مقدار': 5}
# اجرای عملیات اصلی: نام=A, مقدار=5
# لاگ: تابع عملیات_اصلی با نتیجه AAAAA به پایان رسید.
    

این تابع تابع_واسط_لاگ تمام آرگومان‌های دریافتی را ثبت می‌کند و سپس آن‌ها را به تابع اصلی عملیات_اصلی ارسال می‌کند. این روش به شما اجازه می‌دهد تا ویژگی‌های جانبی (cross-cutting concerns) مانند لاگ‌برداری، اعتبار سنجی، یا مدیریت خطا را به توابع موجود اضافه کنید بدون اینکه کد اصلی آن‌ها را تغییر دهید.

جدول مقایسه‌ای: *args در برابر **kwargs

مقایسه ویژگی‌های کلیدی *args و **kwargs
ویژگی توضیح
نماد *args (یک ستاره) برای آرگومان‌های موقعیتی، **kwargs (دو ستاره) برای آرگومان‌های کلیدواژه‌ای
نوع داده‌ای که جمع‌آوری می‌کند *args یک تاپل (Tuple)، **kwargs یک دیکشنری (Dictionary)
ترتیب اهمیت در *args مهم است (چون موقعیتی هستند)، در **kwargs مهم نیست (کلیدها شناسایی‌کننده هستند)
هدف اصلی *args برای دریافت تعداد نامشخصی از آرگومان‌ها، **kwargs برای دریافت تعداد نامشخصی از آرگومان‌های کلیددار/نام‌گذاری شده
مثال تعریف تابع def func(*items): و def func(**data):
مثال فراخوانی تابع (Unpacking) func(*my_list) و func(**my_dict)

عیب‌یابی سریع: مشکلات رایج با *args و **kwargs

این بخش بهت کمک می‌کنه تا مشکلات رایجی که ممکنه هنگام کار با *args و **kwargs باهاشون روبرو بشی رو شناسایی و رفع کنی. درک این موارد باعث می‌شه مهارتتان در دیباگینگ خیلی بهتر بشه.

  • مشکل: خطای TypeError: takes X positional arguments but Y were given

    دلیل: این خطا زمانی رخ می‌ده که تعداد آرگومان‌های موقعیتی که به تابع پاس می‌دی با تعداد مورد انتظار مطابقت نداره. اغلب به دلیل اشتباه در ترتیب آرگومان‌هاست.

    راه حل:

    • مطمئن شو که آرگومان‌های ثابت (non-*args) رو به تعداد صحیح پاس دادی.
    • ترتیب آرگومان‌ها رو چک کن: آرگومان‌های ثابت، بعد *args، و بعد **kwargs.
  • مشکل: خطای TypeError: got multiple values for keyword argument '...'

    دلیل: این خطا وقتی پیش میاد که برای یک آرگومان خاص، هم به صورت موقعیتی (positional) و هم به صورت کلیدواژه‌ای (keyword) مقدار ارسال کردی. یا اگر یک کلید رو چندین بار در **kwargs تکرار کنی.

    راه حل:

    • آرگومان‌های تکراری رو حذف کن.
    • مطمئن شو که آرگومان‌های موقعیتی و کلیدواژه‌ای با هم تداخل ندارند.
  • مشکل: عدم دسترسی به مقادیر داخل args یا kwargs

    دلیل: فراموش کردن این که args یک تاپل و kwargs یک دیکشنری است.

    راه حل:

    • برای دسترسی به آیتم‌های args، از اندیس‌گذاری (مثلاً args[0]) یا حلقه‌ی for استفاده کن.
    • برای دسترسی به آیتم‌های kwargs، از کلیدها (مثلاً kwargs['name']) یا متد .get() یا حلقه‌ی for برای پیمایش .items() استفاده کن.
  • مشکل: پاس ندادن * یا ** هنگام Unpacking

    دلیل: اگر یک لیست یا دیکشنری رو به تابعی که انتظار *args یا **kwargs داره پاس بدی، اما از * یا ** قبل از نام متغیر استفاده نکنی، پایتون اون‌ها رو به عنوان یک آرگومان واحد (نه مجموعه‌ای از آرگومان‌ها) در نظر می‌گیره.

    راه حل:

    • همیشه برای Unpacking لیست/تاپل از * و برای دیکشنری از ** استفاده کن.

سوالات متداول (FAQ Schema)

در این بخش به سوالات رایجی که ممکنه در مورد *args و **kwargs پیش بیاد، پاسخ می‌دیم.

Q: *args و **kwargs دقیقاً چه تفاوتی با هم دارند؟

A: *args برای جمع‌آوری آرگومان‌های موقعیتی (بدون نام) استفاده می‌شود و آن‌ها را به صورت یک تاپل در اختیار تابع قرار می‌دهد. در حالی که **kwargs برای جمع‌آوری آرگومان‌های کلیدواژه‌ای (نام‌گذاری شده) به کار می‌رود و آن‌ها را به صورت یک دیکشنری در تابع مدیریت می‌کند.

Q: آیا می‌توانم از نام‌های دیگری به جای args و kwargs استفاده کنم؟

A: بله، می‌توانید. args و kwargs فقط قرارداد هستند. برای مثال، می‌توانید از *numbers یا **options استفاده کنید. اما برای خوانایی بهتر کد، توصیه می‌شود از همان args و kwargs استفاده کنید.

Q: هنگام استفاده از *args و **kwargs، ترتیب پارامترها چگونه باید باشد؟

A: ترتیب صحیح و استاندارد به این صورت است: 1. آرگومان‌های معمولی (fixed positional arguments) 2. *args 3. آرگومان‌های کلیدواژه‌ای-اجباری (keyword-only arguments) 4. **kwargs. همیشه *args قبل از **kwargs می‌آید.

Q: آیا می‌توانم از * و ** برای ارسال لیست/دیکشنری به تابع استفاده کنم؟

A: بله، این قابلیت به “گسترش آرگومان‌ها” یا Unpacking معروف است. با استفاده از * قبل از یک لیست یا تاپل، آیتم‌های آن به عنوان آرگومان‌های موقعیتی جداگانه به تابع ارسال می‌شوند. با استفاده از ** قبل از یک دیکشنری، کلید-مقدار‌های آن به عنوان آرگومان‌های کلیدواژه‌ای ارسال می‌گردند.

امیدوارم این مقاله جامع، بهت کمک کرده باشه تا مفاهیم *args و **kwargs رو به طور کامل درک کنی و بتونی تو پروژه‌هات با اطمینان و خلاقیت ازشون استفاده کنی. این ابزارها واقعاً می‌تونن کدت رو انعطاف‌پذیرتر و قدرتمندتر کنن. اگه سوالی داشتی یا تجربه‌ای برای به اشتراک گذاشتن، حتماً با ما در میون بذار.

برنامه‌نویسی لذت‌بخش و پرکاربرد!

Table of Contents

آخرین نوشته‌ها