پرش به مطلب اصلی

معرفی توابع

تعریف تابع

فرض کنید که میخواید یک کار پیچیده انجام بدید. مثلا معدل خودتون رو بر اساس تعداد واحد‌های کل، تعداد واحد هر درس و نمره اون درس حساب کنید (میدونم مثالم خیلی تکراریه :( ولی مجبورم). یک راه اینه که تمام کدهایی که نیاز داریم رو یکجا بنویسیم و پشت سر هم ازش استفاده کنیم. اینطوری تعداد خطوط برنامه زیاد میشه و اگر مشکلی توی برنامتون باشه، سخت تر میشه پیدا کردن مشکل! ولی میتونیم برنامه رو به قسمت‌های مختلف تقسیم کنیم که هر قسمت کار خودش رو انجام بده. مثلا یک قسمت، اگر بهش اسم طرف رو بدیم، تعداد واحد کل رو بر میگردونه. قسمت دیگه نمره هر درس و تعداد واحدش رو برمیگردونه. اینطوری برنامه رو عملا به قسمت‌های کوچکتری تقسیم کردیم که کار رو برای نوشتن برنامه‌های بزرگتر راحت تر میکنه.

یا مثلا همین تابع print. اگر به کامپیوتر بگین پرینت که متوجه نمیشه چه کاری باید انجام بده. این تابع کلی کد پشتش داره که ما اصلا کاری با اونا نداریم و فقط از اسم تابع پرینت استفاده می کنیم. یعنی بارها و بارها از یه تکه کد استفاده می کنیم بدون اینکه هر دفعه کلی کد بنویسیم.

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

هر تابع یک سری ورودی که بهشون میگن پارامتر (Parameter) داره (البته گاهی اوقات هم هیچ پارامتری نداره!). مثلا توی مثال بالا، به تابع اسم دانشجو رو میدیم و اون تعداد واحد کل رو برمیگردونه. حالا به تکه کد زیر دقت کنید که روش تعریف تابع توی پایتون رو نشون میده:

def name(parameter):
code

برای اینکار، اول از همه کلمه def رو باید بیاریم. بعدش اسم تابع (نباید تکراری باشه)، بعدش توی پرانتز، اسم پارامترها رو مینویسیم و بعدش : میذاریم. توی خط بعد هم باید کدهای مورد نظرمون رو بنویسیم. اگر درس فاصله گذاری رو نخوندین پیشنهاد میکنم بخونین که اینجا به کار میاد. کد زیر مثال خوبیه:

def example():
print("Avalin tabe touye python!")
z = 3 + 9
print(z)

خب حال این تابع رو تعریف کردیم، به چه دردی میخوره؟

ما تابع example رو تعریف کردیم که یکسری کار انجام میده. هر زمان که بخوایم توی برنامه این کارها انجام بشه، میتونیم فقط بنویسیم ()example و دستورات این تابع انجام میشه. دقیقا مثل تابع print که هرجایی دوست داشتیم پرینت انجام بشه، فقط نوشتیم ()print. حالا برای اینکه مطمئن بشین حرفایی که زدیم درسته، توی shell یا کنسول، دستورات بالا رو با دقت تایپ کنید. بعدش فقط بنویسید ()example مثل عکس زیر:

پارامترهای تابع

هدف از ساخت یک تابع اینه که از یک تکه کد بارها و بارها استفاده کنیم. توی اون درس مثالی زدم که مثلا تابعی داریم که اسم هر کسی رو بدیم، تعداد واحد‌های کل، اسم دروس، نمره و تعداد واحد هر درس رو به ما میده. پس ما یک ورودی به اسم "نام دانشجو" به تابع میدیم و اون هم یه سری چیزا به ما میده. به این ورودی تابع میگن پارامتر. حالا به چه کاری میاد؟ باید دقت کنید که هر کسی از این تابعی که ما نوشتیم میتونه استفاده کنه و هر اسمی دوست داره بده به تابع و اطلاعاتشو بگیره. یعنی برنامه حالت داینامیک میگیره به خودش! مثال زیر رو ببینید:

def tabe_jadid(param1,param2):
javab = param1 + param2
print('avalin parameter =', param1)
print('dovomin parameter=', param2)
print(javab)

tabe_jadid(3,5)

توی تابع بالا، دوتا پارامتر (ورودی) داریم به اسم param1 و param2. توی تابع اول اونها رو با هم جمع میکنیم و جوابش رو میذاریم توی یک متغیر جدید به اسم javab. بعدش سه تا دستور پرینت داریم که فکر کنم دیگه براتون راحت باشه چطور اونها رو بخونید. این میشه تعریف تابعی به اسم tabe_jadid. حالا برای استفاده از این تابع، اسم تابع رو میاریم و پارامترهای مورد نیاز رو "به ترتیب" می نویسیم و اینطوری از این تابع استفاده می کنیم.

برای تعداد پارامترها هیچ محدودیتی نیست. ولی یه زمانی براتون سخته که تمام پارامترها رو به ترتیب بیارید. میتونید اینطوری هم بنویسید و دیگه نیازی نیست به ترتیب باشن:

tabe_jadid(param2=5, param1=3)

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

tabe_jadid(3,5,9)

این کد هم ارور میده:

tabe_jadid(3)

حالا باید راجع به "مقداری که تابع به ما میده" صبحت کنیم. تا الان توابعی که دیدم، فقط یه سری کار انجام میدادن و در نهایت مثلا یه مقداری رو پرینت میکردن. اما فرض کنین ما نمیخوایم چیزی پرینت بگیره. خب اون کاری که تابع کرده باید یه جایی خودشو نشون بده دیگه! مثلا بهش یه عددی بدیم، تابع این عدد رو یه سری دستکاری روش انجام بده و به ما بده. یعنی یه مقداری رو به ما "برگردونه" که مثلا اون مقدار رو بتونیم توی یه متغیر بذاریم. این کار با استفاده از دستور return انجام میشه. به جای این همه توضیح، تابع زیر رو ببینید:

def mesal(param1):
z = param1 * 3
return z

x = mesal(5)
print(x)

توی کد بالا، تابع یک ورودی گرفت و یه خروجی داد. خروجی رو گذاشتیم توی متغیر x.

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

توضیحات بالا مباحث مربوط به پارامترهای تابع رو توضیح داد و به این نکته اشاره کردیم که میتونیم بی نهایت پارامتر برای یه تابع داشته باشیم. توی این قسمت به این نکته میرسیم که داشتن پارامترهای زیاد هم خیلی خوب نیست و ممکنه دردسرساز بشه! اما خوشبختانه راه حل خوبی برای این قضیه هست.

بعضی مواقع به این فکر میکنیم که یک تابع بسازیم که همه چیزش قابل تغییر باشه و کلی "آپشن" به طرف مقابل بدیم. ولی خیلیا با این قضیه مشکل دارن و یک تابع "ساده" با امکانات "پیش فرض" میخوان. مثلا شاید شما هم جزو اون دسته از افراد باشین که خیلی اهل ماشین سواری و کلا دستکاری ماشین هستن. این افراد دوست دارن همه چیز ماشین رو موقع خرید به سلیقه خودشون انتخاب کنن. ولی یه دسته دیگه خیلی به این کار علاقه ندارن و صرفا همون آپشن‌های پیش فرض کارخونه رو میخوان.

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

پس یه مورد جدید معرفی میکنم به اسم مقدار اولیه پارامترهای تابع! این یعنی اینکه کسی که تابع رو مینویسه، یه سری مقادیر پیشفرض به پارامترها میده. هر کسی که دوست داشت میتونه اونها رو تغییر بده ولی اگر کسی حالشو نداشت، میتونه از مقادیر پیشفرض استفاده کنه.

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

def simple(param1, param2=5):
code

کد بالا یه مثال ساده برای تعریف یه تابع به اسم simple هست که دوتا پارامتر داره، num1 که مقدار پیشفرض نداره و num2 که مقدار پیشفرض 5 رو داره.

حالا فرض کنید که میخوایم یک تابع بنویسیم که برامون پنجره تولید کنه. نگاه کنید:

def panjare(toul,arz,jens='sade'):
print(toul,arz,jens)

پس یک تابع تعریف کردیم که طول و عرض و جنس پنجره، پارامترهای اون هستن. حالا میخوایم فراخونیش کنیم. دقت کنید که toul و arz مقدار پیشفرض ندارن ولی jens مقدار پیشفرض داره:

panjare(350,500)

اگر مثل بالا فراخونی کنیم، بدون مشکل اجرا میشه یعنی میتونیم پارامترهایی که مقدار پیشفرض دارن رو اصلن ننویسیم موقع فراخونی. از طرفی میتونیم مثل کد زیر هم فراخونی کنیم. یعنی میتونیم مقدار پیشفرض رو تغییر بدیم:

panjare(350,500,jens='do_jedare')