آموزش پایتون, پایتون سطح متوسط

پارامتر و آرگومان در توابع پایتون؛ آموزش انواع ورودی تابع

پارامتر و آرگومان در توابع پایتون

🗓 آخرین به‌روزرسانی:

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

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

پارامتر و آرگومان چه تفاوتی دارند؟

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

def greet(name):
    print(f"سلام {name}")

greet("مهران")

در این مثال:

  • name پارامتر تابع است.
  • "مهران" آرگومان ارسال‌شده هنگام فراخوانی است.

به‌صورت ساده، پارامتر متغیری است که تابع انتظار دارد و آرگومان داده واقعی است که به آن متغیر تحویل داده می‌شود.

چرا تابع به پارامتر نیاز دارد؟

تابع بدون پارامتر معمولاً هر بار یک رفتار ثابت دارد:

def show_message():
    print("سلام مهران")

اما با تعریف پارامتر می‌توان همان تابع را برای افراد مختلف استفاده کرد:

def show_message(name):
    print(f"سلام {name}")

show_message("مهران")
show_message("سارا")
show_message("علی")

پارامترهای الزامی یا Required Parameters

پارامتری که مقدار پیش‌فرض ندارد، الزامی است. هنگام فراخوانی باید برای آن آرگومان ارسال شود:

def calculate_area(width, height):
    return width * height

area = calculate_area(5, 3)
print(area)

اگر یکی از آرگومان‌ها ارسال نشود، پایتون خطای TypeError ایجاد می‌کند:

calculate_area(5)
TypeError: calculate_area() missing 1 required positional argument: 'height'

آرگومان‌های موقعیتی یا Positional Arguments

در آرگومان‌های موقعیتی، مقدارها براساس ترتیب به پارامترها اختصاص داده می‌شوند:

def introduce(name, city, age):
    print(f"{name}، {age} ساله، ساکن {city}")

introduce("مهران", "استانبول", 30)

پایتون مقدار نخست را به name، مقدار دوم را به city و مقدار سوم را به age می‌دهد.

اهمیت ترتیب آرگومان‌های موقعیتی

اگر ترتیب را اشتباه وارد کنیم، برنامه ممکن است بدون خطا اجرا شود اما نتیجه نادرست باشد:

introduce("استانبول", "مهران", 30)

در این حالت تابع تصور می‌کند «استانبول» نام کاربر و «مهران» نام شهر است.

آرگومان‌های کلیدی یا Keyword Arguments

در آرگومان کلیدی، نام پارامتر را هنگام فراخوانی مشخص می‌کنیم:

def introduce(name, city, age):
    print(f"{name}، {age} ساله، ساکن {city}")

introduce(name="مهران", city="استانبول", age=30)

مزیت اصلی این روش آن است که ترتیب آرگومان‌ها اهمیت کمتری دارد:

introduce(age=30, name="مهران", city="استانبول")

آرگومان‌های کلیدی در توابعی با چند ورودی باعث افزایش خوانایی می‌شوند.

ترکیب آرگومان‌های موقعیتی و کلیدی

می‌توان هر دو نوع را در یک فراخوانی استفاده کرد؛ اما آرگومان‌های موقعیتی باید پیش از آرگومان‌های کلیدی قرار گیرند:

def create_product(name, price, in_stock):
    return {
        "name": name,
        "price": price,
        "in_stock": in_stock
    }

product = create_product("هدفون", 850000, in_stock=True)
print(product)

نسخه زیر نادرست است، زیرا پس از آرگومان کلیدی یک آرگومان موقعیتی آمده است:

create_product(name="هدفون", 850000, True)

این کد خطای نحوی ایجاد می‌کند.

ارسال دوباره مقدار برای یک پارامتر

نباید یک پارامتر را هم به‌صورت موقعیتی و هم به‌صورت کلیدی مقداردهی کنیم:

def greet(name):
    print(name)

greet("مهران", name="سارا")

خطا:

TypeError: greet() got multiple values for argument 'name'

پارامتر دارای مقدار پیش‌فرض

با تعیین مقدار پیش‌فرض، ارسال آرگومان برای آن پارامتر اختیاری می‌شود:

def greet(name, message="سلام"):
    return f"{message} {name}"

print(greet("مهران"))
print(greet("سارا", "خوش آمدی"))

در فراخوانی نخست، مقدار "سلام" استفاده می‌شود. در فراخوانی دوم، مقدار جدید جایگزین مقدار پیش‌فرض شده است.

ترتیب پارامترهای الزامی و پیش‌فرض

پارامترهای الزامی باید پیش از پارامترهای دارای مقدار پیش‌فرض تعریف شوند:

def create_account(username, active=True):
    return {"username": username, "active": active}

تعریف زیر نادرست است:

def create_account(active=True, username):
    pass

پایتون خطای زیر را ایجاد می‌کند:

SyntaxError: non-default argument follows default argument

چند پارامتر پیش‌فرض

def calculate_price(price, discount=0, tax=0):
    discounted_price = price - (price * discount / 100)
    final_price = discounted_price + (discounted_price * tax / 100)
    return final_price

print(calculate_price(100000))
print(calculate_price(100000, discount=10))
print(calculate_price(100000, discount=10, tax=9))

استفاده از نام پارامتر برای گزینه‌های اختیاری، خوانایی فراخوانی تابع را افزایش می‌دهد.

آرگومان‌ها می‌توانند انواع داده مختلف داشته باشند

تابع می‌تواند رشته، عدد، لیست، تاپل، دیکشنری، Set یا هر شیء دیگری دریافت کند:

def calculate_average(scores):
    if len(scores) == 0:
        return 0

    return sum(scores) / len(scores)

print(calculate_average([18, 16, 20, 15]))

نمونه دریافت دیکشنری:

def show_user(user):
    print("نام:", user.get("name", "نامشخص"))
    print("شهر:", user.get("city", "ثبت نشده"))

show_user({"name": "مهران", "city": "استانبول"})

آیا پارامتر نوع داده مشخصی دارد؟

پایتون به‌صورت پیش‌فرض نوع پارامتر را محدود نمی‌کند. تابع زیر با عدد کار می‌کند:

def double(value):
    return value * 2

print(double(5))

اما اگر رشته ارسال شود، رفتار عملگر ضرب برای رشته اجرا می‌شود:

print(double("Python"))

خروجی:

PythonPython

بنابراین باید مشخص کنیم تابع چه نوع داده‌ای انتظار دارد و در صورت نیاز ورودی را اعتبارسنجی کنیم.

اعتبارسنجی آرگومان‌ها داخل تابع

def calculate_discount(price, percent=0):
    if not isinstance(price, (int, float)):
        return "قیمت باید عدد باشد"

    if price < 0:
        return "قیمت نمی‌تواند منفی باشد"

    if percent < 0 or percent > 100:
        return "درصد تخفیف باید بین صفر تا صد باشد"

    return price - (price * percent / 100)

print(calculate_discount(500000, 15))

راهنمای نوع یا Type Hint برای پارامترها

Type Hint مشخص می‌کند انتظار داریم پارامتر و مقدار برگشتی چه نوعی داشته باشند:

def calculate_total(price: float, quantity: int) -> float:
    return price * quantity

راهنمای نوع معمولاً اجرای برنامه را محدود نمی‌کند، اما خوانایی کد و عملکرد ابزارهای بررسی کد را بهبود می‌دهد.

استفاده از None برای مقدار اختیاری

گاهی می‌خواهیم نبودن یک مقدار را از مقدار واقعی آن تشخیص دهیم. در این شرایط None انتخاب مناسبی است:

def create_profile(name, bio=None):
    if bio is None:
        bio = "توضیحی ثبت نشده است"

    return {
        "name": name,
        "bio": bio
    }

print(create_profile("مهران"))

خطر پارامتر پیش‌فرض قابل‌تغییر

قرار دادن لیست یا دیکشنری به‌عنوان مقدار پیش‌فرض می‌تواند نتیجه‌ای غیرمنتظره ایجاد کند:

def add_task(task, tasks=[]):
    tasks.append(task)
    return tasks

print(add_task("مطالعه"))
print(add_task("ورزش"))

لیست پیش‌فرض فقط یک بار هنگام تعریف تابع ساخته می‌شود؛ بنابراین فراخوانی‌های بعدی همان لیست قبلی را استفاده می‌کنند.

روش امن‌تر:

def add_task(task, tasks=None):
    if tasks is None:
        tasks = []

    tasks.append(task)
    return tasks

ارسال لیست یا تاپل با عملگر ستاره

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

def introduce(name, city, age):
    return f"{name}، {age} ساله، ساکن {city}"

user_data = ("مهران", "استانبول", 30)
print(introduce(*user_data))

این کد معادل فراخوانی زیر است:

introduce("مهران", "استانبول", 30)

تعداد و ترتیب عناصر باید با پارامترهای تابع هماهنگ باشد.

ارسال دیکشنری با دو ستاره

با ** می‌توان کلیدهای دیکشنری را به‌عنوان نام پارامتر و مقدارهای آن را به‌عنوان آرگومان ارسال کرد:

def create_user(name, city, age):
    return {
        "name": name,
        "city": city,
        "age": age
    }

user_data = {
    "name": "مهران",
    "city": "استانبول",
    "age": 30
}

print(create_user(**user_data))

نام کلیدها باید با نام پارامترهای تابع مطابقت داشته باشد.

پارامترهای فقط موقعیتی

در پایتون می‌توان با علامت / تعیین کرد برخی پارامترها فقط به‌صورت موقعیتی ارسال شوند:

def divide(number1, number2, /):
    return number1 / number2

print(divide(10, 2))

فراخوانی زیر مجاز نیست:

divide(number1=10, number2=2)

این قابلیت بیشتر در طراحی APIها و توابع کتابخانه‌ای کاربرد دارد.

پارامترهای فقط کلیدی

با قرار دادن * در تعریف تابع می‌توان پارامترهای بعد از آن را فقط به‌صورت کلیدی دریافت کرد:

def create_order(product, quantity, *, discount=0, express=False):
    return {
        "product": product,
        "quantity": quantity,
        "discount": discount,
        "express": express
    }

order = create_order(
    "کتاب پایتون",
    2,
    discount=10,
    express=True
)

این روش برای گزینه‌هایی که ممکن است اشتباه یا جابه‌جا شوند، خوانایی و ایمنی بیشتری ایجاد می‌کند.

تفاوت پارامتر پیش‌فرض با آرگومان کلیدی

  • پارامتر پیش‌فرض هنگام تعریف تابع مشخص می‌شود.
  • آرگومان کلیدی هنگام فراخوانی تابع با نام پارامتر ارسال می‌شود.
def greet(name, message="سلام"):
    return f"{message} {name}"

print(greet(name="مهران", message="خوش آمدی"))

در این مثال message پارامتر پیش‌فرض است و message="خوش آمدی" آرگومان کلیدی محسوب می‌شود.

خطاهای رایج پارامتر و آرگومان

ارسال آرگومان کمتر از نیاز تابع

def add(a, b):
    return a + b

add(5)

ارسال آرگومان بیشتر از نیاز تابع

add(5, 10, 20)

استفاده از نام کلیدی نامعتبر

def greet(name):
    return f"سلام {name}"

greet(username="مهران")

خطای معمول:

TypeError: greet() got an unexpected keyword argument 'username'

جابه‌جایی آرگومان‌های موقعیتی

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

استفاده از لیست پیش‌فرض مشترک

برای مقدارهای پیش‌فرض قابل‌تغییر از None استفاده کنید و شیء جدید را داخل تابع بسازید.

پروژه اول: محاسبه مبلغ سفارش

تابع زیر آرگومان‌های الزامی، پیش‌فرض و فقط کلیدی را در یک پروژه واقعی ترکیب می‌کند:

def calculate_order(
    product_name,
    unit_price,
    quantity=1,
    *,
    discount=0,
    tax=0,
    shipping=0
):
    if unit_price < 0 or quantity <= 0:
        return {"success": False, "message": "قیمت یا تعداد نامعتبر است"}

    if not 0 <= discount <= 100:
        return {"success": False, "message": "درصد تخفیف نامعتبر است"}

    if tax < 0:
        return {"success": False, "message": "مالیات نامعتبر است"}

    subtotal = unit_price * quantity
    discount_amount = subtotal * discount / 100
    after_discount = subtotal - discount_amount
    tax_amount = after_discount * tax / 100
    final_total = after_discount + tax_amount + shipping

    return {
        "success": True,
        "product": product_name,
        "quantity": quantity,
        "subtotal": subtotal,
        "discount": discount_amount,
        "tax": tax_amount,
        "shipping": shipping,
        "total": final_total
    }

order = calculate_order(
    "کتاب آموزش پایتون",
    250000,
    2,
    discount=10,
    tax=9,
    shipping=50000
)

if order["success"]:
    print("محصول:", order["product"])
    print("تعداد:", order["quantity"])
    print("مبلغ نهایی:", order["total"])
else:
    print(order["message"])

پروژه دوم: ساخت پروفایل کاربر

def create_profile(
    name,
    email,
    *,
    city="ثبت نشده",
    age=None,
    skills=None,
    active=True
):
    if skills is None:
        skills = []

    profile = {
        "name": name.strip(),
        "email": email.strip().lower(),
        "city": city,
        "age": age,
        "skills": skills.copy(),
        "active": active
    }

    return profile

user = create_profile(
    "مهران",
    "MEHRAN@example.com",
    city="استانبول",
    age=30,
    skills=["Python", "WordPress"]
)

print(user)

تمرین‌های پیشنهادی

  1. تابعی بنویسید که نام و نام خانوادگی را دریافت کند و نام کامل را برگرداند.
  2. تابعی بسازید که طول و عرض را بگیرد و مساحت مستطیل را محاسبه کند.
  3. برای تابع محاسبه قیمت، پارامتر پیش‌فرض تخفیف تعریف کنید.
  4. تابعی بنویسید که نام، سن و شهر را با آرگومان‌های کلیدی دریافت کند.
  5. تابعی طراحی کنید که لیست نمرات را بگیرد و کمترین، بیشترین و میانگین را برگرداند.
  6. تابعی بنویسید که با مقدار پیش‌فرض None یک فهرست خرید جدید ایجاد کند.
  7. یک تاپل شامل سه آرگومان بسازید و با * به تابع ارسال کنید.
  8. یک دیکشنری مطابق نام پارامترهای تابع بسازید و با ** ارسال کنید.
  9. تابعی با دو پارامتر فقط کلیدی برای مالیات و تخفیف طراحی کنید.
  10. پروژه سفارش را طوری توسعه دهید که کد تخفیف و هزینه ارسال رایگان را نیز مدیریت کند.

📌 همچنین بخوانید: بازار کار پایتون در ایران، دستورهای break، continue و pass در پایتون و ساخت ربات تلگرام با پایتون

پرسش‌های متداول

تفاوت پارامتر و آرگومان چیست؟

پارامتر هنگام تعریف تابع نوشته می‌شود؛ آرگومان مقدار واقعی است که هنگام فراخوانی به تابع می‌دهیم.

آیا می‌توان ترتیب آرگومان‌ها را تغییر داد؟

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

آیا همه پارامترها باید مقدار پیش‌فرض داشته باشند؟

خیر. فقط ورودی‌هایی که واقعاً اختیاری هستند باید مقدار پیش‌فرض داشته باشند.

چرا برای لیست پیش‌فرض از None استفاده می‌کنیم؟

زیرا لیست پیش‌فرض فقط یک بار ساخته می‌شود و بین فراخوانی‌ها مشترک می‌ماند. استفاده از None اجازه می‌دهد در هر فراخوانی یک لیست مستقل بسازیم.

عملگرهای * و ** هنگام فراخوانی چه کاری انجام می‌دهند؟

* عناصر لیست یا تاپل را به آرگومان‌های موقعیتی و ** جفت‌های دیکشنری را به آرگومان‌های کلیدی تبدیل می‌کند.

جمع‌بندی

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

در درس بعدی با محدوده متغیرها در پایتون؛ متغیرهای Local و Global آشنا می‌شویم.

ادامه مسیر یادگیری پایتون

برای یادگیری منظم، آموزش‌های مرتبط زیر را به‌ترتیب دنبال کنید:

می‌خواهی پیشرفتت ذخیره شود؟با ورود یا ثبت‌نام رایگان، درس‌های تمام‌شده را علامت بزن و درصد پیشرفتت را در حساب کاربری ببین.ورود / ثبت‌نام برای ذخیره پیشرفت
درس بعدی · دوره پایتون متوسط (6 از 18)محدوده متغیرها در پایتون؛ تفاوت Local و Global ←
آموزش‌های تازه، کد آماده و رفع خطاهر هفته در کانال Dev Source؛ رایگان.
🧭 مسیر یادگیری پایتون از صفر
ماژول 6: توابع — درس 25 از 44

برای ذخیره پیشرفت در همه دستگاه‌ها و دریافت گواهی پایان مسیر، رایگان ثبت‌نام کن یا وارد شو.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *