آموزش پایتون به زبان ساده: توابع

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

توابع در واقع تکه کدهایی هستند که برای انجام یه سری وظایفی نوشته میشن و با یه نام مشخصی میشه به اونا دسترسی داشت.

مزایای توابع

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

تعریف یک تابع

در تعریف توابع باید یه سری نکات از جمله عبارات کلیدی و نام‌گذاری‌ها رعایت بشه. در ادامه به کمک یه مثال با نحوه‌ی تعریف توابع آشنا میشیم:

def greet_user():
    print(‘Hello!’)

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

فراخوانی و اجرای تابع

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

def greet_user():
    print(‘Hello!’)
greet_user()

ارسال اطلاعات به تابع

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

def greet_user(name):
    print(f’Hello {name}’)
greet_user(‘ali‘)
greet_user(‘hossein‘)

توضیح:
اگه دقت کنید همون تابع بالایی رو با یه سری تغییرات کوچک بازنویسی کردیم.
در بخش تعریف تابع، داخل () ها متغیری با نام name نوشتیم که در واقع این متغیر، آرگومان این تابع هستش.
در بدنه تابع از تابع f-string استفاده کردیم که یه رشته‌ای رو که شامل hello و اون مقدار name هستش رو برمی‌گردونه.
تو بخش بدنه تابع، ما هیچ اطلاعی از مقدار name نداریم و یه مقدار متغیر هستش که هنگام فراخوانی تابع مقداردهی میشه.

در ادامه ما دو بار این تابع رو فراخوانی کردیم یا اصطلاحا صدا زدیم.
یه بار رشته‌ی ali رو به عنوان آرگومان فرستادیم، یه بار هم رشته hossein رو.

چند نکته در استفاده از آرگومان‌ها

  • ما در استفاده از آرگومان‌ها تنها به یه مورد محدود نیستیم و می‌تونیم چندین آرگومان تعریف کنیم. بدین صورت که باید با کاراکتر , از هم‌دیگه جدا بشن.
  • آرگومان‌های ما می‌تونن از هر نوعی باشن. مثل رشته، عدد، لیست، دیکشنری و…
  • در استفاده از آرگومان‌ها ترتیب اهمیت زیادی داره و باید هنگام تعریف توابع و فراخوانی اونا به ترتیب آرگومان‌ها دقت کنید.

آرگومان‌های کلیدی

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

def greet_user(f_name, l_name):
    print(f’Hello {f_name} {l_name}’)
greet_user(l_name=’ahmadi’, f_name =’ali’)

توضیح:
اگه دقت کنید، در بخش تعریف تابع در ابتدا متغیر f_name یا نام خانوادگی اومده و بعد از اون l_name.
اما در زمان فراخوانی تابع این ترتیب آرگومان‌ها رعایت نشده و در عوض مقادیر رو بر اساس نام متغیرهای تعریف شده در قسمت تعریف تابع نسبت دادیم.

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

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

def greet_user(f_name, l_name=‘unknown’):
    print(f’Hello {f_name} {l_name}’)
greet_user(‘ali’,’ahmadi’)
greet_user(‘ali’)

توضیح:
در این مثال ما یه تابع داریم که دو تا پارامتر داره که پارامتر دومی دارای مقدار پیش‌فرض unknown هستش.
ادامه‌ی تابع هم مشابه مثال‌های قبل هستش.
در ادامه ما دوبار تابع رو فراخوانی کردیم.
در دفعه‌ی اول هر دو تا آرگومان رو برای تابع فرستادیم و خب نتیجه‌ای هم که بدست میاریم، مشخصه و هر دو تا رو نشون میده.
اما در دفعه‌ی دوم تنها آرگومان اول یعنی f_name رو وارد کردیم و مقداری برای آرگومان دوم در نظر نگرفتیم. اگه خروجی رو دقت کنید، مقدار l_name رو برابر مقدار پیش‌فرض unknown در نظر گرفته و اونو چاپ کرده.
اگه دقت کرده باشین، تو این حالت دیگه خطایی نداریم. چون حداقل یه مقدار پیش‌فرضی برای آرگومان موردنظرمون در نظر گرفته شده.

برگرداندن مقادیر

تا اینجا ما با توابعی کار کردیم که به اونها یه سری ورودی میدادند و مثلا یه عملیاتی مثل خروجی در صفحه نمایش رو انجام میدادند. اما توابع قابلیت‌های بیشتری هم دارند و اون برگرداندن مقادیر هستش. مثلا فرض کنید ما یه تابعی تعریف می‌کنیم برای محاسبه‌ی محیط یه مستطیل. در ابتدا برای تابع باید ورودی در نظر بگیریم. ورودی‌های ما عبارتنداز : طول (tool) و عرض (arz)
ما قراره که یه مقداری رو هم به عنوان خروجی این تابع برگردونیم. بیاین با یه مثال نحوه‌ی برگردوندن مقادیر رو توضیح بدیم:

def get_mohit(tool, arz):
    result = (tool + arz) * 2
 return result
mohit = get_mohit(2, 4)
print(mohit)

توضیح:
در ابتدا ما یه تابع با نام get_mohit تعریف کردیم که دو تا پارامتر یا ورودی داره: طول (tool) و عرض (arz)
در بدنه تابع، تو خط اول یه متغیر تعریف کردیم با نام result که قراره حاصل نتیجه‌ی محاسبه فرمول روبرو در اون ذخیره بشه.
در خط بعد ما مقدار result رو به عنوان خروجی بر می‌گردونیم که برای اینکار از کلمه کلیدی return استفاده شده.

حالا بریم سراغ برنامه‌ی اصلی:
در ابتدا ما یه متغیر تعریف کردیم با نام mohit که قراره خروجی تابع get_mohit در اون ریخته بشه.
آرگومان‌های ما تو این مثال ۲ و ۴ هستند. در ابتدا این دو مقدار برای تابع موردنظر فرستاده میشن. بعد از اون تابع عملیات محاسباتی رو انجام میده و در نهایت خروجی رو برمی‌گردونه و به متغیر مورد نظر تو بخش فراخوانی که در اینجا mohit هستش انتساب میده.
و در نهایت هم مقدار متغیر mohit توی صفحه چاپ میشه.

ذخیره توابع در ماژول‌ها

تصور کنید که کد شما شامل چندین تابع هستش. در حالت عادی ما میایم و همه‌ی اونا رو توی یه فایل می‌نویسیم. اما گاهی اوقات دنبال کردن این حجم از کد کار دشواری میشه. به ویژه برای کارهای تیمی که هر کسی یه بخش خاصی رو دنبال می‌کنه. در این مواقع بهتره که برخی از توابع‌مون رو که با همدیگه ارتباط دارند توی فایل‌های جداگانه‌ای بنویسیم و هر وقت نیاز شد در فایل اصلی به اونا دسترسی پیدا کنیم و اونا رو اجرا کنیم. به این فایل‌های جداگانه که توابع ما توی اونا ذخیره میشن اصطلاحا ماژول (‌module) میگن.
برای دسترسی به توابعی که در ماژول‌ها مختلفی ذخیره شدند کافیه که در کدمون اونا رو import کنیم.
استفاده‌ از ماژول‌ها مزایای مختلفی داره. مثلا:
جزییات بخش‌هایی از کد که لازم نیست از دید ما پنهان میشه و لازم نیست که اونا رو دنبال کنیم.
کد ما جمع و جورتر میشه و منظم‌تر میشه.

خب اجازه بدین در ادامه با چند مثال با نحوه‌ی کار با اونا آشنا بشیم.

ابتدا یه فایل جدید ایجاد کنید و کدهای زیر رو در اون بنویسید و با نام hello.py ذخیره کنید.

def greet_user():
    print(‘Hello how are you?’)

حالا در کنار این فایلی که ایجاد کردین، یه فایل جدید دیگه بنویسین کدهای زیر رو در اون وارد کنید:

import hello
hello.greet_user()

توضیح:
در ابتدا ما یه فایل به نام hello.py ساختیم و داخلش یه تابع تعریف کردیم.
سپس یه فایل کنار اون فایل ایجاد کردیم و کدهای بالا رو نوشتیم که در ادامه قصد دارم اونو توضیح بدم:
در ابتدا کلمه کلیدی import رو می‌نویسیم و بعد از اون نام module یا همون فایلی که توابع ما داخلش ذخیره شده‌اند رو می‌نویسیم.
در ادامه برای فراخوانی تابع موجود در ماژول موردنظر کافیه که ابتدا اسم اون ماژول و بعد کاراکتر . و بعد نام تابع رو بنویسیم.

به عبارتی سینتکس کلی فراخوانی تابع از یه ماژول به این صورته:

module_name.function_name()

ایمپورت کردن توابع خاص

در حالت قبل برنامه میاد در ابتدا کل توابع و محتویات موجود در اون ماژول رو کپی می‌کنه و بعد از اون استفاده می‌کنه. اما گاهی اوقات لازم نیس که تمام محتویات یه ماژول رو لود کنیم و تنها به یه توابع خاصی نیاز داریم. در این حالت می‌تونیم به کمک سینتکس زیر توابع موردنظرمون از ماژول مرتبط رو لود کنیم و از اون استفاده کنیم.

from module_name import function_name

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

from hello import greet_user
greet_user()

توضیح:
اگه دقت کنید تو این حالت دیگه لازم نیست که برای فراخوانی تابع موردنظر، اسم ماژول رو هم در ابتدا ذکر کنید و فقط کافیه که نام تابع رو صدا بزنید.

اختصاص نام مستعار به توابع و ماژول‌ها به کمک as

گاهی اوقات اسم توابع موردنظر ما خیلی طولانی‌اند یا اینکه نام اون توابع با نام یه تابع موجود در فایل اصلی یکسان هستند و اینجاست که ممکنه برامون یه خورده دردسر ایجاد کنه. اینجا بهتره که از نام مستعار استفاده کنیم. ما با استفاده از کلمه کلیدی as می‌تونیم اسامی کوچک‌تری رو برای توابع‌مون تعریف کنیم و در طول برنامه از اونها استفاده کنیم. سینتکس استفاده از اونا به شکل زیر هستش:

from module_name import function_name as fn

همچنین ما می‌تونیم برای ماژول‌ها هم یه نام مستعار در نظر بگیریم. سینتکس استفاده از اون در ادامه اومده:

import module_name as mn

ایمپورت کردن تمام توابع یک ماژول

دیدیم که با استفاده از سینتکس قبل می‌تونیم توابع خاصی از یه ماژول رو لود کنیم و یه خوبی‌ای هم که نسبت به حالت قبل داشت اینه که برای فراخوانی تابع موردنظر، لازم نیست که نام ماژول هم در ابتدای اون بیاد. اما گاهی اوقات ما قصد داریم که به کمک این سینتکس تمام توابع ماژول موردنظر رو import کنیم. در این حالت کافیه که به جای نام توابع فقط کاراکتر * رو بنویسیم. یعنی به صورت زیر:

from module_name import *

جمع‌بندی

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

این قسمت هم به پایان رسید. امیدوارم از مطالبی که تو این مقاله نوشته شده بود لذت برده باشین.


منبع: آموزش پایتون به زبان ساده: توابع - وبسایت شخصی محمدحسین میثاق‌پور