Kahibaro
Discord Login Register

فصل ۹: توابع

چرا توابع مهم هستند؟

در برنامه‌نویسی، توابع مثل «بلوک‌های سازنده» هستند که از آن‌ها برای ساختن برنامه‌های بزرگ‌تر استفاده می‌کنیم. چند دلیل مهم بودن توابع:

یک مثال ساده از استفادهٔ تابع به‌جای تکرار کد:

# بدون تابع (تکرار کد)
r1 = 5
area1 = 3.14 * r1 * r1
r2 = 10
area2 = 3.14 * r2 * r2
print(area1, area2)
# با تابع
def circle_area(r):
    return 3.14 * r * r
print(circle_area(5), circle_area(10))

در نسخهٔ دوم، اگر فرمول را عوض کنیم، فقط داخل تابع circle_area را تغییر می‌دهیم.

تعریف توابع

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

$$
\text{def} \ \text{name}(\text{parameters}): \\
\quad \text{body}
$$

به‌صورت کد:

def name(parameters):
    # بدنهٔ تابع
    # دستورها
    # ...

نکته‌ها:

مثال: یک تابع ساده بدون ورودی و بدون خروجی

def say_hello():
    print("سلام!")
    print("به دنیای پایتون خوش آمدی.")
# فراخوانی تابع
say_hello()

اینجا:

محل تعریف تابع

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

پارامترها و آرگومان‌ها

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

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

def greet(name):
    print("سلام", name)
greet("علی")
greet("زهرا")

چند پارامتر

def add(a, b):
    print("جمع =", a + b)
add(3, 5)      # a = 3, b = 5
add(10, 20)    # a = 10, b = 20

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

پارامترهای پیش‌فرض (default parameters)

می‌توانیم برای بعضی پارامترها مقدار پیش‌فرض تعریف کنیم. اگر آرگومانِ مربوطه را ندهیم، پایتون آن مقدار پیش‌فرض را استفاده می‌کند.

def power(base, exponent=2):
    print(base ** exponent)
power(3)      # 3 به توان 2 -> 9
power(2, 3)   # 2 به توان 3 -> 8

اینجا:

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

def f(a, b=10):   # درست
    ...
# def f(a=10, b):   # نادرست، خطا می‌دهد
#     ...

آرگومان‌های نام‌گذاری‌شده (keyword arguments)

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

def introduce(name, age):
    print("نام:", name)
    print("سن:", age)
introduce(name="علی", age=25)
introduce(age=30, name="مهدی")  # ترتیب مهم نیست

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

مقادیر بازگشتی

بعضی تابع‌ها فقط کاری انجام می‌دهند (مثل چاپ روی صفحه) و چیزی «برنمی‌گردانند». بعضی دیگر نتیجهٔ محاسبه را برمی‌گردانند تا بتوانیم بعداً از آن استفاده کنیم. برای برگرداندن مقدار از کلمهٔ کلیدی return استفاده می‌کنیم.

def add(a, b):
    result = a + b
    return result
x = add(3, 5)   # نتیجهٔ تابع در x ذخیره می‌شود
print(x)

نکته‌ها:

def multiply(a, b):
    return a * b
print(multiply(4, 6))

تابع بدون `return`

اگر در تابع از return استفاده نکنیم (یا return بدون مقدار بنویسیم)، مقدار بازگشتی تابع None است.

def show_message():
    print("پیام مهم!")
result = show_message()
print(result)   # چاپ می‌کند: None

اینجا:

بازگشت چند مقدار

در پایتون می‌توانیم چند مقدار را با هم برگردانیم. در واقع یک تاپل برگردانده می‌شود:

def get_min_max(numbers):
    smallest = min(numbers)
    largest = max(numbers)
    return smallest, largest
mn, mx = get_min_max([3, 8, 1, 9, 4])
print("کمترین:", mn)
print("بیشترین:", mx)

پایتون به‌طور خودکار مقادیر برگردانده‌شده را «باز می‌کند» (unpack) و در متغیرهای mn و mx می‌ریزد.

محدودهٔ متغیرها (محلی در برابر سراسری)

وقتی با توابع کار می‌کنیم، مهم است بدانیم هر متغیر کجا قابل استفاده است؛ به این مفهوم می‌گویند محدودهٔ متغیر (scope).

متغیر محلی (local)

متغیری که داخل تابع تعریف می‌شود، فقط داخل همان تابع قابل استفاده است.

def say_name():
    name = "علی"    # متغیر محلی
    print(name)
say_name()
# print(name)  # خطا: name تعریف نشده است

اینجا name فقط داخل say_name وجود دارد. بیرون تابع، پایتون این نام را نمی‌شناسد.

متغیر سراسری (global)

متغیری که خارج از همهٔ توابع تعریف شود، در سراسر فایل (در تابع‌ها هم) در دسترس است (با بعضی نکات مهم).

message = "سلام سراسری!"   # متغیر سراسری
def show():
    print(message)   # می‌تواند به message دسترسی داشته باشد
show()
print(message)

تابع می‌تواند مقدار متغیر سراسری را بخواند. اما اگر داخل تابع به آن مجدداً مقداردهی کنیم، اتفاق دیگری می‌افتد.

سایه‌انداختن (shadowing)

اگر داخل تابع متغیری با همان نام متغیر سراسری تعریف کنیم، متغیر محلی، متغیر سراسری را «پوشش» می‌دهد:

x = 10  # سراسری
def test():
    x = 5   # محلی، سراسری را نمی‌سازد و فقط در این تابع معتبر است
    print("داخل تابع:", x)
test()
print("بیرون تابع:", x)

خروجی:

داخل تابع: 5
بیرون تابع: 10

تغییر متغیر سراسری داخل تابع

اگر واقعاً بخواهیم داخل تابع، متغیر سراسری را عوض کنیم، باید از کلمهٔ global استفاده کنیم (این کار معمولاً در برنامه‌های بزرگ توصیه نمی‌شود، مگر با احتیاط):

count = 0
def increase():
    global count     # اعلام می‌کنیم که منظورمان متغیر سراسری است
    count = count + 1
increase()
increase()
print(count)   # 2

اگر global count را ننویسیم و داخل تابع به count مقدار بدهیم، در واقع یک count محلی جدید ساخته می‌شود که جدا از متغیر سراسری است.

توصیهٔ مهم

استفادهٔ مجدد از کد

یکی از مهم‌ترین دلایل استفاده از توابع، قابلیت استفادهٔ مجدد (reusability) است؛ یعنی:

مثال: اعتبارسنجی سن

فرض کنید چند جای برنامه باید بررسی کنیم سن واردشده معتبر است یا نه (مثلاً بین ۰ و ۱۲۰).

بدون تابع:

age = int(input("سن را وارد کنید: "))
if age < 0 or age > 120:
    print("سن نامعتبر است")
else:
    print("سن معتبر است")
# جای دیگر برنامه
age2 = int(input("سن دوم را وارد کنید: "))
if age2 < 0 or age2 > 120:
    print("سن نامعتبر است")
else:
    print("سن معتبر است")

با تابع:

def is_valid_age(age):
    return 0 <= age <= 120
age = int(input("سن را وارد کنید: "))
if is_valid_age(age):
    print("سن معتبر است")
else:
    print("سن نامعتبر است")
age2 = int(input("سن دوم را وارد کنید: "))
if is_valid_age(age2):
    print("سن دوم معتبر است")
else:
    print("سن دوم نامعتبر است")

اینجا:

ساختن کتابخانهٔ توابع شخصی

وقتی توابع مفید زیادی نوشتید (مثلاً توابعی برای محاسبات خاص، کار با رشته‌ها، پردازش فایل‌ها)، می‌توانید:

این یعنی کد شما واقعاً «قابل استفادهٔ مجدد» می‌شود، نه فقط در یک فایل، بلکه در چند پروژهٔ مختلف.

نکته‌های طراحی تابع‌های قابل‌استفادهٔ مجدد

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

Views: 7

Comments

Please login to add a comment.

Don't have an account? Register now!