خانه » آموزش Python » آموزش توابع در پایتون (Functions)

آموزش توابع در پایتون (Functions)

✍️ محمود کاظمی 🔄 ۲۸ آذر ۱۴۰۴ ⏱ حدود ۲ دقیقه

مقدمه

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

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

ساختار پایه‌ای تعریف تابع

ساده‌ترین شکل تعریف تابع با کلمه کلیدی def انجام می‌شود. ساختار عمومی شامل نام تابع، پارامترها و بدنه تابع است. در مثال زیر یک تابع ساده برای جمع دو عدد نشان داده شده است:

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

توضیح کوتاه

در مثال بالا تابع add دو پارامتر a و b را می‌گیرد و با استفاده از return نتیجه را برمی‌گرداند. همین الگو پایه‌ی تمام توابع در پایتون است و هر تابع در پایتون می‌تواند از این ساختار استفاده کند.

پارامترها و انواع آنها

پارامترها در توابع می‌توانند به شکل‌های مختلفی تعریف شوند: پارامترهای موقعیتی (positional)، پارامترهای کلیدی (keyword)، پارامترهای پیش‌فرض، و پارامترهای متغیر (*args و **kwargs). در ادامه هر کدام با مثال آمده است.

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

def greet(name, greeting='Hello'):
    return f\"{greeting}, {name}!\"

این تابع یک پارامتر موقعیتی name و یک پارامتر پیش‌فرض greeting دارد. می‌توانید آن را به صورت greet(‘Ali’) یا greet(‘Ali’, greeting=’Salam’) فراخوانی کنید. استفاده از پارامترهای پیش‌فرض کمک می‌کند که توابع انعطاف‌پذیرتر شوند.

*args و **kwargs

برای پذیرش تعداد متغیری از آرگومان‌ها از *args و **kwargs استفاده می‌شود. این ویژگی برای نوشته‌های عمومی و کتابخانه‌ها بسیار مفید است.

def summarize(*args, **kwargs):
    print('Positional:', args)
    print('Keyword:', kwargs)

مثال بالا نشان می‌دهد که چگونه می‌توان چند مقدار موقعیتی و چند مقدار کلیدی را دریافت و پردازش کرد. این الگو برای بازنویسی wrapperها یا decoratorها معمول است.

بازگرداندن مقادیر (return)

یک تابع در پایتون می‌تواند صفر یا چند مقدار بازگرداند. بازگرداندن چند مقدار عملاً به صورت tuple انجام می‌شود:

def stats(numbers):
    total = sum(numbers)
    count = len(numbers)
    avg = total / count if count else 0
    return total, count, avg

فراخوانی total, count, avg = stats([1,2,3]) مقدارها را جداگانه برمی‌گرداند. همچنین استفاده از NamedTuple یا dataclass برای خوانایی بهتر توصیه می‌شود.

تایپ هینت‌ها و مستندسازی

از نسخه‌های جدید پایتون، تایپ هینت‌ها تسهیل شده‌اند. تایپ هینت به خواننده و ابزارهای تحلیل کد کمک می‌کند. همچنین استفاده از docstring استاندارد برای هر تابع ضروری است.

from typing import List, Tuple

def average(numbers: List[float]) -> float:
    \"\"\"Return the average of a list of numbers.\"\"\"
    return sum(numbers) / len(numbers)

استفاده از تایپ هینت و docstring باعث می‌شود IDEها و ابزارهایی مانند mypy یا linters بتوانند اشکالات احتمالی را در زمان توسعه نشان دهند.

توابع بی‌نام (lambda) و کاربردها

برای توابع بسیار کوتاه که تنها یک عبارت دارند می‌توان از lambda استفاده کرد. در محیط‌های مدرن، lambda برای تعریف سریع توابع در عبارت‌هایی مانند sorted یا map کاربردی است.

nums = [3, 1, 4, 2]
sorted_by_value = sorted(nums, key=lambda x: x)

اگرچه lambda مفید است، اما برای خوانایی بهتر در توابع پیچیده از def و نامگذاری مناسب استفاده کنید.

توابع تو در تو و closure

پایتون امکان تعریف تابع داخل تابع را فراهم می‌کند. این الگو برای ساخت حالت محصور (closure) یا ساخت decorator ساده مناسب است.

def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

times3 = make_multiplier(3)
print(times3(5))  # خروجی: 15

در مثال بالا تابع multiplier به n دسترسی دارد حتی پس از اینکه make_multiplier خاتمه یافته باشد. چنین رفتارهایی قدرتمند ولی باید با احتیاط استفاده شوند.

مثال عملی: تابع محاسبه میانگین وزنی

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

from typing import List

def weighted_mean(values: List[float], weights: List[float]) -> float:
    \"\"\"Compute weighted mean. Raises ValueError on invalid input.\"\"\"
    if len(values) != len(weights):
        raise ValueError('values and weights must have same length')
    total_weight = sum(weights)
    if total_weight == 0:
        raise ValueError('sum of weights must not be zero')
    return sum(v * w for v, w in zip(values, weights)) / total_weight

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

نکات و بهترین شیوه‌ها

  • نام‌گذاری واضح: نام تابع باید نشان‌دهنده‌ی کار آن باشد.
  • یک وظیفه، یک تابع: تابع‌ها باید تک‌مسئله‌ای باشند.
  • استفاده از تایپ هینت و docstring برای خوانایی و ابزارهای تحلیل.
  • اجتناب از پارامترهای قابل تغییر به عنوان مقدار پیش‌فرض (مانند list=[]).
  • نوشتن تست‌های واحد برای توابع حیاتی و بازگشت‌های مرزی.

اشتباهات رایج

چند خطای معمول در نوشتن تابع در پایتون عبارتند از: استفاده از مقدار پیش‌فرض قابل تغییر، فراموش کردن return، یا عدم اعتبارسنجی ورودی‌ها. همیشه قبل از انتشار کد، edge caseها را بررسی کنید.

جمع‌بندی

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

منابع و گام‌های بعدی

  • تمرین: بازنویسی توابع با تایپ هینت و نوشتن تست واحد.
  • مطالعه PEPهای مرتبط با typing و function annotations.
  • آشنایی با ابزارهایی مانند mypy، pytest و linters برای تضمین کیفیت کد.

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