~/icsd.ir — bash
SYSTEM_ONLINE

توابع

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

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

چرا تابع؟

فرض کنید می‌خواهید مالیات یک قیمت را چندین بار حساب کنید:

# بدون تابع - تکرار کد
price1 = 100000
tax1 = price1 * 0.09
total1 = price1 + tax1

price2 = 250000
tax2 = price2 * 0.09
total2 = price2 + tax2

# با تابع - بسیار بهتر
def calculate_total(price, tax_rate=0.09):
    tax = price * tax_rate
    return price + tax

total1 = calculate_total(100000)
total2 = calculate_total(250000)
total3 = calculate_total(500000, tax_rate=0.10)

تعریف تابع

def greet():
    """تابع ساده‌ای که سلام می‌کند"""
    print("سلام!")

# فراخوانی
greet()    # سلام!

# با پارامتر
def greet_user(name):
    print(f"سلام {name}!")

greet_user("علی")        # سلام علی!
greet_user("زهرا")       # سلام زهرا!

# با مقدار بازگشتی
def square(x):
    return x ** 2

result = square(5)        # 25
print(square(7))          # 49

Docstring

توضیح تابع با رشته سه‌گانه – مهم برای کد حرفه‌ای:

def calculate_bmi(weight, height):
    """محاسبه شاخص توده بدنی (BMI).
    
    Args:
        weight (float): وزن به کیلوگرم
        height (float): قد به متر
    
    Returns:
        float: شاخص BMI
    
    Examples:
        >>> calculate_bmi(70, 1.75)
        22.86
    """
    return weight / (height ** 2)

# دسترسی به docstring
print(calculate_bmi.__doc__)
help(calculate_bmi)

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

پارامترهای موقعیتی (Positional)

def divide(a, b):
    return a / b

print(divide(10, 2))     # 5.0
print(divide(2, 10))     # 0.2  ← ترتیب مهم است!

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

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

# با کلید (ترتیب مهم نیست)
create_user(age=25, name="علی", city="کاشان")
create_user(name="زهرا", city="تهران", age=30)

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

def greet(name, greeting="سلام"):
    print(f"{greeting} {name}!")

greet("علی")                 # سلام علی!
greet("زهرا", "درود")        # درود زهرا!
greet("محمد", greeting="هی") # هی محمد!
⚠️ تله مقدار پیش‌فرض تغییرپذیر:

# غلط!
def add_item(item, items=[]):    # ← این لیست بین فراخوانی‌ها مشترک است!
    items.append(item)
    return items

print(add_item("a"))    # ['a']
print(add_item("b"))    # ['a', 'b']  ← لیست جدید نیست!

# درست
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

تعداد متغیر آرگومان: *args

def sum_all(*args):
    """مجموع هر تعداد عدد"""
    return sum(args)

print(sum_all(1, 2, 3))           # 6
print(sum_all(1, 2, 3, 4, 5))     # 15
print(sum_all())                  # 0

# args یک تاپل است
def show_args(*args):
    print(type(args))             # <class 'tuple'>
    for arg in args:
        print(arg)

show_args("a", "b", "c")

آرگومان‌های کلیدی متغیر: **kwargs

def create_profile(**kwargs):
    """ساخت پروفایل با هر تعداد ویژگی"""
    for key, value in kwargs.items():
        print(f"{key}: {value}")

create_profile(name="علی", age=25, city="کاشان")

# kwargs یک دیکشنری است
def show_kwargs(**kwargs):
    print(type(kwargs))           # <class 'dict'>
    print(kwargs)

show_kwargs(a=1, b=2, c=3)

ترکیب همه با هم

def complex_func(name, age=18, *args, **kwargs):
    print(f"name={name}, age={age}")
    print(f"args={args}")
    print(f"kwargs={kwargs}")

complex_func("علی", 25, "extra1", "extra2", city="کاشان", job="dev")
# name=علی, age=25
# args=('extra1', 'extra2')
# kwargs={'city': 'کاشان', 'job': 'dev'}

Unpacking در فراخوانی

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

# با لیست/تاپل
nums = [1, 2, 3]
print(add(*nums))         # 6  معادل add(1, 2, 3)

# با دیکشنری
params = {"a": 1, "b": 2, "c": 3}
print(add(**params))      # 6  معادل add(a=1, b=2, c=3)

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

def get_min_max(numbers):
    return min(numbers), max(numbers)

# دریافت تاپل
result = get_min_max([3, 1, 4, 1, 5, 9])
print(result)    # (1, 9)

# unpacking
low, high = get_min_max([3, 1, 4, 1, 5, 9])
print(low, high)    # 1 9

# بدون return - یعنی None برمی‌گردد
def no_return():
    print("سلام")

x = no_return()
print(x)    # None

# return زودهنگام
def find_first_even(numbers):
    for n in numbers:
        if n % 2 == 0:
            return n
    return None    # هیچ زوج نبود

حوزه (Scope)

x = 100    # متغیر سراسری (Global)

def my_func():
    y = 50    # متغیر محلی (Local)
    print(x)  # دسترسی به سراسری OK
    print(y)  # 50

my_func()
# print(y)  # NameError - y محلی است

# تغییر سراسری از داخل تابع
counter = 0

def increment():
    global counter
    counter += 1

increment()
increment()
print(counter)    # 2

# nonlocal برای closure
def outer():
    x = 10
    def inner():
        nonlocal x
        x += 1
    inner()
    print(x)    # 11

outer()

قاعده LEGB

پایتون متغیرها را به این ترتیب می‌گردد:

  1. Local – تابع جاری
  2. Enclosing – تابع بیرونی (در closure)
  3. Global – فایل/ماژول
  4. Built-in – پایتون

توابع لامبدا

تابع بی‌نام تک‌خطی:

# تابع معمولی
def double(x):
    return x * 2

# لامبدا معادل
double = lambda x: x * 2

print(double(5))    # 10

# با چند پارامتر
add = lambda a, b: a + b
print(add(3, 5))    # 8

# کاربرد رایج: در sort/filter/map
prices = [("A", 100), ("B", 50), ("C", 75)]
prices.sort(key=lambda x: x[1])
print(prices)
# [('B', 50), ('C', 75), ('A', 100)]

# با filter
nums = [1, 2, 3, 4, 5, 6, 7, 8]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)    # [2, 4, 6, 8]

# با map
squared = list(map(lambda x: x**2, nums))
print(squared)
💡 توصیه:

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

توابع توکار مهم

# map - اعمال تابع روی هر عضو
nums = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, nums))
print(squared)    # [1, 4, 9, 16]

# filter - فیلتر بر اساس شرط
positives = list(filter(lambda x: x > 0, [-2, -1, 0, 1, 2]))
print(positives)    # [1, 2]

# reduce - کاهش به یک مقدار
from functools import reduce
product = reduce(lambda a, b: a * b, [1, 2, 3, 4, 5])
print(product)    # 120

# sum, min, max, all, any
print(sum([1, 2, 3]))       # 6
print(min([3, 1, 4]))       # 1
print(max([3, 1, 4]))       # 4
print(all([True, True, False]))    # False
print(any([False, False, True]))   # True

# sorted با key
words = ["python", "is", "awesome"]
sorted_by_len = sorted(words, key=len)
print(sorted_by_len)    # ['is', 'python', 'awesome']

توابع بازگشتی

# فاکتوریل
def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))    # 120

# فیبوناچی
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

for i in range(10):
    print(fib(i), end=" ")
# 0 1 1 2 3 5 8 13 21 34

تمرین فصل

🏋️ تمرین ۱: تابعی بنویسید که عددی بگیرد و True برگرداند اگر اول است.
🏋️ تمرین ۲: تابعی بنویسید که لیستی از اعداد بگیرد و میانگین، انحراف معیار و واریانس را برگرداند.
🏋️ تمرین ۳: تابعی بنویسید که قیمت و تخفیف (به‌صورت پارامتر کلیدی با مقدار پیش‌فرض ۰) بگیرد و قیمت نهایی را چاپ کند.
🏋️ تمرین ۴: با لامبدا، لیستی از کلمات را بر اساس طول مرتب کنید (نزولی).

جمع‌بندی

  • تعریف تابع با def و docstring
  • پارامترها: موقعیتی، کلیدی، پیش‌فرض، *args، **kwargs
  • Unpacking با * و ** در فراخوانی
  • بازگشت چند مقدار با تاپل
  • Scope: Local، Enclosing، Global، Built-in
  • توابع لامبدا برای موارد ساده
  • توابع توکار: map، filter، reduce، sorted

نمایش سایت

رنگ سایت
حالت نمایش
اندازهٔ متن
خوانایی

این تنظیمات فقط روی مرورگر شما ذخیره می‌شود.