آموزش تابع ها در python. توابع بلوکهای کدی هستند که برای انجام یک کار خاص تعریف میشوند و میتوانند به طور مکرر در برنامه فراخوانی شوند. استفاده از توابع باعث بهبود خوانایی، سازماندهی و کارایی کد میشود و همچنین امکان استفاده مجدد از کدها را فراهم میآورد.
1. تعریف توابع در پایتون
ساختار پایه یک تابع در پایتون
برای تعریف یک تابع در پایتون از کلمه کلیدی def استفاده میکنیم. ساختار پایه به شکل زیر است:
def function_name(parameters): # بدنه تابع # عملیاتی که باید انجام شود return result
function_name: نام تابع است که باید با قوانین نامگذاری متغیرها همخوانی داشته باشد.
parameters: ورودیهای تابع هستند که میتوانند صفر یا بیشتر از یک عدد باشند. این پارامترها میتوانند دادههایی مانند اعداد، رشتهها، یا هر نوع داده دیگر باشند.
return: این کلمه کلیدی برای بازگرداندن نتیجه از تابع استفاده میشود. اگر return نباشد، تابع مقدار None را باز میگرداند.
1.1 تعریف یک تابع ساده
یک تابع ساده که هیچ پارامتری ندارد و تنها یک پیغام چاپ میکند:
def greet():
print("Hello, welcome to Python!")
برای فراخوانی این تابع از نام آن استفاده میکنیم:
greet()
خروجی:
Hello, welcome to Python!
1.2 تابع با پارامتر
در این مثال، تابع add_numbers دو پارامتر میگیرد و حاصل جمع آنها را برمیگرداند:
def add_numbers(a, b): return a + b
برای استفاده از این تابع باید مقادیر را به آن ارسال کنیم:
result = add_numbers(3, 5) print(result)
خروجی:
8
1.3 تابع با مقدار پیشفرض برای پارامتر
اگر بخواهیم پارامتری در تابع داشته باشیم که مقدار پیشفرضی داشته باشد، میتوانیم آن را به شکل زیر تعریف کنیم:
def greet(name="Guest"):
print(f"Hello, {name}!")
در این مثال، اگر نامی برای پارامتر name ارسال نشود، مقدار پیشفرض “Guest” استفاده میشود:
greet() # خروجی: Hello, Guest!
greet("Alice") # خروجی: Hello, Alice!
1.4 تابع با چندین پارامتر
میتوانید توابعی با تعداد زیادی پارامتر تعریف کنید. به عنوان مثال:
def multiply(x, y, z): return x * y * z
برای فراخوانی آن:
result = multiply(2, 3, 4) print(result)
خروجی:
24
1.5 استفاده از *args و **kwargs
گاهی اوقات نیاز داریم که تعداد پارامترهای ورودی را نامحدود کنیم. برای این منظور میتوانیم از *args (برای پارامترهای پوزیشنال) و **kwargs (برای پارامترهای کلیدی) استفاده کنیم.
*args: به تابع اجازه میدهد که هر تعداد آرگومان پوزیشنال دریافت کند.
**kwargs: به تابع اجازه میدهد که هر تعداد آرگومان کلیدی (keyword arguments) دریافت کند.
def example_function(a, b, *args, **kwargs): print(a, b) print(args) # پارامترهای اضافی پوزیشنال print(kwargs) # پارامترهای اضافی کلیدی
فراخوانی تابع:
example_function(1, 2, 3, 4, 5, x=10, y=20)
خروجی:
1 2
(3, 4, 5)
{'x': 10, 'y': 20}
1.6 توابع بازگشتی (Recursion)
میتوان توابعی تعریف کرد که خودشان را فراخوانی کنند. به این نوع توابع، توابع بازگشتی گفته میشود. یک مثال ساده از تابع بازگشتی برای محاسبه فاکتوریل یک عدد:
def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1)
برای استفاده از این تابع:
print(factorial(5))
خروجی:
120
در این مثال، تابع factorial خود را برای مقادیر کمتری از n فراخوانی میکند تا زمانی که به n == 0 برسد که در آن صورت مقدار 1 باز میگرداند.
نکات مهم در مورد توابع
پارامترهای پیشفرض: در صورتی که پارامتری را ارسال نکنیم، پایتون از مقدار پیشفرض آن استفاده میکند.
مقدار بازگشتی (Return): استفاده از return در یک تابع باعث میشود که تابع مقداری را به فراخوانیکننده بازگرداند. اگر از return استفاده نشود، تابع به طور پیشفرض مقدار None را باز میگرداند.
توابع بدون آرگومان: تابع میتواند بدون هیچ پارامتری تعریف شود و هیچ آرگومانی را نیاز نداشته باشد.
استفاده از *args و **kwargs: این ویژگیها به شما اجازه میدهند که تعداد نامحدودی از آرگومانها را به تابع ارسال کنید.
توابع بازگشتی: توابع بازگشتی بسیار مفید هستند، اما باید مراقب عمق بازگشت باشید، زیرا ممکن است باعث خطای “Stack Overflow” شود.
2. پارامترها و مقادیر بازگشتی
توابع میتوانند پارامترها را به عنوان ورودی دریافت کنند و مقادیر را به عنوان خروجی بازگردانند. این دو ویژگی، یعنی پارامترها و مقادیر بازگشتی (Return values)، بخشهای اساسی هر تابع را تشکیل میدهند.
2.1 پارامترها در توابع
پارامترها متغیرهایی هستند که به یک تابع ارسال میشوند و تابع از آنها برای انجام عملیات استفاده میکند. وقتی یک تابع تعریف میشود، شما میتوانید تعداد دلخواهی پارامتر برای آن مشخص کنید. پارامترها میتوانند ضروری یا اختیاری باشند.
پارامترهای پوزیشنال (Positional parameters):
این پارامترها باید در هنگام فراخوانی تابع به ترتیب خاصی ارسال شوند.
def greet(name, age):
print(f"Hello, {name}. You are {age} years old.")
greet("Alice", 30) # فراخوانی با پارامترهای پوزیشنال
خروجی:
.Hello, Alice. You are 30 years old
پارامترهای پیشفرض (Default parameters):
میتوانید مقادیر پیشفرض برای پارامترها تعیین کنید. اگر این پارامترها در هنگام فراخوانی ارسال نشوند، مقدار پیشفرض استفاده میشود.
def greet(name="Guest"):
print(f"Hello, {name}")
greet() # استفاده از مقدار پیشفرض
greet("Alice") # ارسال مقدار جدید
خروجی:
Hello, Guest Hello, Alice
پارامترهای نامحدود با *args (Arguments):
این نوع پارامتر برای دریافت تعداد نامحدودی از آرگومانهای پوزیشنال استفاده میشود. آرگومانها به صورت یک تاپل به تابع ارسال میشوند.
def sum_numbers(*args): return sum(args) print(sum_numbers(1, 2, 3, 4)) # مجموع چهار عدد
خروجی:
10
پارامترهای کلیدی نامحدود با **kwargs (Keyword Arguments):
این نوع پارامتر برای دریافت تعداد نامحدودی از آرگومانهای کلیدی (که به صورت key=value هستند) استفاده میشود. این آرگومانها به صورت یک دیکشنری به تابع ارسال میشوند.
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, city="New York")
خروجی:
name: Alice age: 30 city: New York
2.2 مقادیر بازگشتی (Return values)
توابع میتوانند مقادیر مختلفی را با استفاده از کلمه کلیدی return بازگردانند. اگر تابع مقداری را باز نگرداند، به طور پیشفرض مقدار None باز میگرداند.
استفاده از return برای بازگشت یک مقدار:
تابعی را در نظر بگیرید که دو عدد را میگیرد و مجموع آنها را برمیگرداند:
def add(a, b): return a + b result = add(3, 5) print(result)
خروجی:
8
در اینجا، تابع add حاصل جمع دو عدد را با استفاده از return باز میگرداند.
تابع بدون return:
اگر در یک تابع هیچ مقدار بازگشتی نداشته باشیم، به طور پیشفرض مقدار None باز میگردد.
def greet(name):
print(f"Hello, {name}")
result = greet("Alice")
print(result) # چون تابع مقدار بازگشتی ندارد، مقدار None برمیگردد
خروجی:
Hello, Alice None
در اینجا، تابع greet فقط پیامی را چاپ میکند و هیچ مقداری را باز نمیگرداند. بنابراین، مقدار None به طور خودکار برمیگردد.
استفاده از return برای بازگشت چندین مقدار:
میتوانید چندین مقدار را در یک تابع با استفاده از return بازگردانید. این مقادیر به صورت یک تاپل باز میگردند.
def get_coordinates():
return 10, 20
x, y = get_coordinates()
print(f"x: {x}, y: {y}")
خروجی
x: 10, y: 20
در اینجا، تابع get_coordinates دو مقدار را باز میگرداند و ما آنها را در دو متغیر x و y ذخیره میکنیم.
بازگشت تابعی به نام تابع بازگشتی (Recursion):
توابع بازگشتی توابعی هستند که خودشان را فراخوانی میکنند. در این نوع توابع نیز میتوان از return برای بازگشت مقدار استفاده کرد.
یک مثال ساده از تابع بازگشتی برای محاسبه فاکتوریل یک عدد:
def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1) result = factorial(5) print(result)
خروجی:
120
در اینجا، تابع factorial خود را برای مقادیر کوچکتر از n فراخوانی میکند تا فاکتوریل عدد را محاسبه کند.
2.3 ترکیب پارامترها و مقادیر بازگشتی
همچنین میتوانیم پارامترها و مقادیر بازگشتی را با هم ترکیب کنیم. به عنوان مثال، یک تابع میتواند چندین پارامتر بگیرد و سپس یک مقدار را بازگرداند:
def calculate_area(length, width): return length * width area = calculate_area(5, 3) print(area)
خروجی:
15
نکات مهم
پارامترهای اختیاری: با استفاده از مقادیر پیشفرض برای پارامترها، میتوانیم تابعی بسازیم که برخی از پارامترهای آن اختیاری باشند.
پارامترهای نامحدود: با استفاده از *args و **kwargs میتوانیم توابعی بسازیم که تعداد نامحدودی پارامتر پوزیشنال یا کلیدی را بپذیرند.
مقدار بازگشتی None: اگر تابعی هیچ مقدار بازگشتی نداشته باشد، مقدار پیشفرض None برمیگرداند.
توابع بازگشتی: میتوان از توابع بازگشتی برای حل مسائل پیچیده استفاده کرد. در این نوع توابع، return به محاسبات در مراحل مختلف کمک میکند.
3. توابع پیشفرض و نامگذاری شده
توابع میتوانند پارامترهای پیشفرض داشته باشند و همچنین میتوانند از پارامترهای نامگذاری شده (keyword arguments) استفاده کنند. این ویژگیها باعث میشوند که توابع انعطافپذیرتر و قابل استفادهتر باشند.
3.1 توابع پیشفرض (Default Functions)
توابع پیشفرض به توابعی گفته میشود که در آنها برای برخی از پارامترها، مقادیر پیشفرض تعیین میشود. این مقادیر زمانی که فراخوانی تابع بدون ارسال مقدار برای آن پارامترها انجام شود، استفاده خواهند شد.
مثال از توابع پیشفرض:
def greet(name="Guest", age=30):
print(f"Hello, {name}. You are {age} years old.")
در این تابع، پارامترهای name و age مقدار پیشفرض دارند. اگر هنگام فراخوانی تابع مقدار خاصی برای این پارامترها ارسال نشود، مقادیر پیشفرض بهطور خودکار استفاده میشوند.
فراخوانی تابع:
greet() # استفاده از مقادیر پیشفرض
greet("Alice") # ارسال مقدار برای پارامتر `name`
greet("Bob", 40) # ارسال مقادیر برای هر دو پارامتر
خروجی:
Hello, Guest. You are 30 years old. Hello, Alice. You are 30 years old. Hello, Bob. You are 40 years old.
در اینجا:
در فراخوانی اول، مقادیر پیشفرض name=”Guest” و age=30 استفاده میشود.
در فراخوانی دوم، فقط مقدار جدید برای name ارسال شده و age همچنان پیشفرض باقی میماند.
در فراخوانی سوم، هر دو پارامتر مقدار جدیدی دریافت میکنند.
نکات در مورد توابع پیشفرض:
پارامترهای پیشفرض باید همیشه پس از پارامترهای بدون پیشفرض در تعریف تابع قرار گیرند. یعنی ابتدا پارامترهایی که باید حتماً مقداردهی شوند (غیر اختیاری) و سپس پارامترهای اختیاری که مقدار پیشفرض دارند.
# اشتباه است!
def greet(name="Guest", age):
print(f"Hello, {name}. You are {age} years old.")
3.2 توابع با پارامترهای نامگذاری شده (Keyword Arguments)
میتوانید هنگام فراخوانی تابع به جای استفاده از موقعیت (position) پارامترها، از نام آنها برای ارسال مقادیر استفاده کنید. به این نوع پارامترها پارامترهای نامگذاری شده (keyword arguments) گفته میشود. این امکان به شما این اجازه را میدهد که مقادیر پارامترها را به صورت مشخص و نامگذاری شده ارسال کنید، بدون اینکه نگران ترتیب آنها باشید.
مثال از توابع با پارامترهای نامگذاری شده:
def describe_person(name, age, city):
print(f"Name: {name}, Age: {age}, City: {city}")
هنگام فراخوانی این تابع، میتوانید پارامترها را به صورت نامگذاری شده ارسال کنید:
describe_person(age=25, city="New York", name="Alice")
خروجی:
Name: Alice, Age: 25, City: New York
در اینجا:
پارامترها بر اساس نامشان به تابع ارسال شدهاند.
ترتیب پارامترها اهمیت ندارد زیرا هر کدام با نامشان مشخص شدهاند.
مزایای استفاده از پارامترهای نامگذاری شده:
وضوح بیشتر: وقتی از پارامترهای نامگذاری شده استفاده میکنید، کد خواناتر میشود زیرا مشخص است که هر پارامتر چه مقدار را دریافت میکند.
مناسب برای توابع با تعداد زیاد پارامتر: وقتی تابعی تعداد زیادی پارامتر دارد، استفاده از نامهای پارامتر باعث میشود که فراخوانی تابع به وضوح مشخص باشد.
ترکیب با توابع پیشفرض: میتوانید از پارامترهای نامگذاری شده برای تغییر تنها برخی از مقادیر پیشفرض استفاده کنید.
ترکیب پارامترهای پیشفرض و نامگذاری شده:
def greet(name="Guest", age=30, city="Unknown"):
print(f"Hello, {name}. You are {age} years old, and you live in {city}.")
greet(name="Alice", age=25) # استفاده از پارامترهای نامگذاری شده
خروجی:
Hello, Alice. You are 25 years old, and you live in Unknown
در اینجا:
مقدار name و age از طریق پارامترهای نامگذاری شده ارسال شدهاند.
پارامتر city از مقدار پیشفرض استفاده کرده است چون در فراخوانی تابع مقداری برای آن ارسال نشده است.
3.3 استفاده از پارامترهای پیشفرض و نامگذاری شده در ترکیب با *args و **kwargs
در برخی مواقع، میخواهید توابعی با تعداد نامحدودی از آرگومانها داشته باشید که هم از *args (برای پارامترهای پوزیشنال) و هم از **kwargs (برای پارامترهای کلیدی) پشتیبانی کنند.
def example_function(a, b=10, *args, **kwargs):
print(f"a = {a}, b = {b}")
print("Additional positional arguments:", args)
print("Additional keyword arguments:", kwargs)
example_function(5, 20, 30, 40, x=100, y=200)
خروجی:
a = 5, b = 20
Additional positional arguments: (30, 40)
Additional keyword arguments: {'x': 100, 'y': 200}
در اینجا:
a یک پارامتر معمولی است.
b یک پارامتر پیشفرض است که مقدار آن در صورت ارسال نشدن از مقدار پیشفرض استفاده میکند.
*args پارامترهای اضافی پوزیشنال را به صورت تاپل میگیرد.
**kwargs پارامترهای اضافی کلیدی را به صورت دیکشنری میگیرد.
