فصل ۱۰: توابع در پایتون

۱۰.۱ | چرا باید از توابع استفاده کنیم؟
- جلوگیری از تکرار کد: هر جا کدی تکراری دیدی، وقتشه تبدیلش کنی به تابع.
- ساختاردهی کد: کدها به تکههای کوچک و قابل مدیریت تقسیم میشن.
- آسانتر شدن ایرادیابی: اگر مشکلی پیش بیاد، دقیقاً میدونی تو کدوم تابع باید دنبال خطا بگردی.
- امکان استفاده مجدد: تابعی که یک بار نوشتی رو میتونی هزار بار صدا بزنی.
- تسهیل در تیمورک: هر عضو تیم میتونه یک تابع رو بنویسه و سر همشون کنید.
۱۰.۲ | قواعد تعریف تابع
فرمت کلی تعریف تابع در پایتون:
def my_function(parameters):
# کدهای تابع
return [مقدار خروجی اختیاری]
- کلمه
defبرای معرفی تابع. - اسم تابع طبق قواعد نامگذاری متغیّرها.
- درون پرانتز میتونی پارامترها رو بنویسی.
- بلاک مربوط به تابع باید با یک تورفتگی (indentation) شروع بشه.
- استفاده از کلمه
returnبرای خروجی دادن (اختیاریه، اگر ننویسی، تابعNoneبرمیگردونه.)
مثال
def hi():
print("سلام دوستان!")
فراخوانی:
hi()
۱۰.۳ | مقدار برگشتی (return)
هر وقت return برسه تابع متوقف و مقدارش برگشت داده میشه.
def add(a, b):
return a + b
print(add(2, 3)) # خروجی: 5
اگر هیچ چیز برنگردونی خود به خود خروجی تابع
Noneهست.
def test():
print("hello")
result = test()
print(result) # خروجی: None
۱۰.۴ | پارامترها و آرگومانها (Parameters & Arguments)
تفاوت:
- پارامتر: نام متغیّری که داخل تعریف تابع مینویسی
- آرگومان: مقدار واقعی که موقع صدا زدن تابع میفرستی
مثال:
def greet(name): # name = پارامتر
print("سلام", name)
greet("علی") # "علی" = آرگومان
پارامتر پیشفرض
اگر برای پارامتر مقدار اولیه بذاری، اجباری نیست موقع صدا زدن آرگومان بدی.
def greet(name="مهمان"):
print("سلام", name)
greet() # خروجی: سلام مهمان
greet("نازنین")# خروجی: سلام نازنین
۱۰.۵ | آرگومانهای دلخواه و کلیدواژهای (*args و **kwargs)
گاهی نمیدونی چند تا آرگومان کاربر میفرسته. اینجاست که دو تکنیک زیر کاربرد دارن:
*args: لیست از آرگومانهای اضافه (با ترتیب)
def summation(*numbers):
print(numbers)
return sum(numbers)
print(summation(1, 3, 5)) # خروجی: 9
- خروجی: آرگومانها به صورت tuple به تابع میرسند.
**kwargs: دیکشنری از آرگومانهای کلیدواژهای (بدون ترتیب)
def user_info(**data):
print(data)
for k, v in data.items():
print(k, ":", v)
user_info(name="سامان", city="مشهد")
# {'name': 'سامان', 'city': 'مشهد'}
# name : سامان
# city : مشهد
۱۰.۶ | دامنهی متغیّرها (Variable Scope)
- متغیّر سراسری (Global): متغیری که بیرون از همه توابع تعریف شده.
- متغیّر محلی (Local): متغیری که داخل تابع تعریف شده و فقط همونجا قابل استفادهست.
مثال:
x = 10 # سراسری
def foo():
y = 5 # محلی
print("x:", x) # اوکی
print("y:", y) # اوکی
foo()
print("x:", x) # اوکی
print("y:", y) # خطا: y وجود ندارد
اگر داخل یک تابع بخوای متغیری سراسری رو تغییر بدی باید global استفاده کنی:
count = 0
def inc():
global count
count += 1
inc()
print(count) # خروجی: 1
۱۰.۷ | توابع بازگشتی (Recursive Functions)
تابعی که خودش را صدا میزند (کاربرد: فاکتوریل، فیبوناچی و …)
مثال فاکتوریل:
def factorial(n):
if n == 1:
return 1
return n * factorial(n-1)
print(factorial(5)) # خروجی: 120
- باید یک شرط پایان حتماً داشته باشه که به بینهایت نره!
۱۰.۸ | مستندسازی توابع (Docstring)
زیر تعریف تابع میتونی توضیح بنویسی که تابع چه کار میکنه.
این متن موقع کمک گرفتن یا با دستور help نمایش داده میشه.
def greet(name):
"""
تابعی برای سلام دادن به شخص با نام داده شده
"""
print("سلام", name)
۱۰.۹ | توابع لامبدا (Lambda Functions)
توابع یکخطی، بدون اسم.
- کاربرد اصلی: وقتی یک تابع ساده و موقت لازم داری.
- فرمت:
python lambda پارامتر: خروجی
مثال مقایسهای:
def square(x):
return x**2
# معادل
sq = lambda x: x**2
print(square(3)) # خروجی: 9
print(sq(3)) # خروجی: 9
ترکیب با توابع دیگر (map, filter, etc):
nums = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, nums))
print(squared) # خروجی: [1, 4, 9, 16]
۱۰.۱۰ | توابع تو در تو و Closure
میتوانیم توابع را داخل هم تعریف کنیم. تابع داخلی فقط در محدوده تابع بیرونی قابل استفاده است.
گاهی این مدلبندی برای مخفی کردن بخشی از کد یا ایجاد توابع خصوصی استفاده میشه.
مثال:
def outer():
msg = "Hello"
def inner():
print(msg) # از متغیر outer به راحتی استفاده میکنه
return inner
hi = outer()
hi() # خروجی: Hello
۱۰.۱۱ | توابع به عنوان آرگومان
تابع در پایتون هم در واقع یک متغیره، میتونی بهش مثل یک عدد یا رشته، مقدار بدی یا منتقلش کنی.
این امکان برنامهنویسی تابعی (Functional Programming) رو فراهم میکنه.
مثال:
def say_hi():
print("Hi there")
def greet(some_function):
some_function()
greet(say_hi) # خروجی: Hi there
۱۰.۱۲ | چند نکته مهم و حرفهای
- از توابع کوتاه و کاملاً تخصصی استفاده کن.
- هر تابع فقط یک کار انجام بده
- نام گذاریت واضح باشه
- اگر قراره مقدار زیادی داده بین توابع جابهجا بشه، بهتره با ساختارهای دادهای مثل دیکشنری یا لیست منتقل کنی.
- از Docstring غافل نشو، چون وقتی پروژه بزرگ شد خیلی به کارت میاد!
- تابعها رو تست کن. برای سیستمی کردن تست، بعدها میتونی با unittest آشنا بشی.
۱۰.۱۳ | تمرین های فصل توابع
۱. تابعی بنویس که یک لیست عدد رو بگیره و مجموع اعداد زوج رو برگردونه.
۲. تابعی بنویس که یک رشته بگیره و اگر palindrom بود (از هر دو سمت یکی بود) True برگردونه.
۳. یک تابع بازگشتی بنویس که Nامین عدد فیبوناچی رو برگردونه.
۴. تفاوت return و print رو با مثال نشون بده.