کتاب عصر پایتون/فصل پنجم: کار با توابع
کتاب عصر پایتون به کمک علاقهمندان ایرانی پایتون جمع آوری شده است
اين كتاب بر اساس مجوز گنو ارايه میگردد [۱]
فصل پنجم: کار با توابع
ویرایشتابع چیست؟
ویرایشتابع، مجموعهای از کدها یا قطعه کدی است که با یک نام خاص یا محدودۀ اسمی یکتا شناخته میشود. بنابراین یک تابع به دفعات زیادی میتواند اجرا شود. با استفاده از توابع میتوان پارامترهایی را به کد مورد نظر ارسال کرده و نتایج حاصله از آن ورودی را دریافت کرد. پس نتیجۀ یک تابع میتواند در دفعات مختلف اجرا متفاوت باشد. برای تعريف و استفاده از توابع در پایتون از عبارتهایی ویژه و از پیش تعیین شدۀ def ، return و global استفاده میشود که در ادامۀ درس به توضیح هریک پرداخته میشود.
چرا از توابع استفاده میکنیم؟
ویرایشقبل از ورود به جزئیات بهتر است یک دید کلی از توابع و نحوۀ کار آنها بهدست آوریم. بسیاری از شما حتماً با توابع و نحوۀ استفاده از آنها آشنایی دارید. استفاده از توابع یکی از سادهترین و در عین حال قویترین و پرکاربردترین روشهای برنامهنویسی است که هنوز هم استفاده زیادی دارد. توابع در حالت کلی دو نقش و هدف مهم برنامهنویسی را برآورده میکنند:
1- استفادۀ مجدد از کد
ویرایشهمانند بسیاری از زبانهای دیگر، توابع در پایتون آسانترین روش برای قطعهبندی منطقی کد برای استفادۀ مجدد در زمان و مکانی دیگر هستند. تمام کدهای نوشته شده بهصورت متوالی و سریع اجرا میشوند. با استفاده از توابع میتوان از بخشی از کد به دفعات متعدد استفاده کرد.
2- تجزیۀ رویهای
ویرایشهمچنین با استفاده از توابع، کل برنامه به رویهها یا بخشهایی کوچک و مشخص تجزیه میشود. در این حالت برنامهنویس میتواند بهصورت جداگانه روی بخشهای مختلف کار کند. هریک از این بخشها یا توابع کار مشخصی انجام میدهند. پس یک مسئلۀ پیچیده و بزرگ به مسایل کوچک و روشنی تقسیم شده و هر یک جداگانه پیادهسازی میشود.
اصول توابع در پایتون
ویرایشدر فصلهای قبل شما با توابع کار کردید! برای مثال تابع len که طول یک متغییر چندقسمتی را بر میگرداند. در این فصل شما یاد خواهید گرفت که توابع جدید ایجاد کنید.
نحوۀ تعریف تابع
ویرایشدر زبان پایتون برای تعریف یک تابع جدید از دستور def استفاده میشود. نام تابع، درست بعد از عبارت def ظاهر میشود و در مقابل نام تابع و در داخل پرانتز، تنها نام پارامترهای قابل دریافت توسط تابع نوشته میشود. در نهایت همانند اعلان سایر قطعهکدهای موجود با کاراکتر دو نقطه (:) به اتمام میرسد. در ادامه، با رعایت کردن تورفتگی، کدهای داخل تابع نوشته میشود.
بازگشت مقدار از تابع
ویرایشزمانی که یک تابع، فراخوانی میشود، فراخوانندۀ تابع تا زمان اتمام کار تابع و برگشت نتیجه، منتظر میماند. در حقیقت روند اجرای برنامه از سطر فراخوانده شده به داخل تابع منتقل شده و پس از اتمام کار از سطر بعدی، ادامه مییابد. در صورتی که تابعی بخواهد مقداری را به عنوان نتیجۀ کار برگشت دهد، از دستور return برای انجام این کار استفاده میکند.
استفاده از متغیرهای سراسری
ویرایشمتغیرها global است.
ارسال پارامتر به تابع
ویرایشدر پایتون ارسال متغییر به توابع از طریق مقداردهی صورت میگیرد. این مقداردهی و ارسال آرگومانها به توابع بر خلاف زبانهای C و ++C بهصورت مرجع (reference) است. یعنی همان متغییر و نه یک کپی از آن به تابع ارسال میشود. پس هر گونه دستکاری آن در داخل تابع باعث تغییر متغییر اصلی خواهد شد. حتی با تغییر نام و مقداردهی دوباره به متغییری جدید باعث ایجاد متغییر جدیدی در حافظه نخواهد شد! و فقط دادۀ موجود یک نام (اشارهگر) جدید خواهد داشت.
مقداردهی پیشفرض پارامترها
ویرایشدر هنگام فراخوانی تابع باید به هر پارامتر آن یه مقدار نسبت داد (فرستاد). و در صورتی که مقداری به یک پارامتر فرستاده نشود باعث بروز خطای برنامهنویسی خواهد شد. برای جلوگیری از این حالت پایتون شما را قادر میسازد تا برای پارمترهای تابع خود مقدار پیشفرض نسبت دهید. این کار را میتوانید در هنگام تعریف تابع و با نسبت دادن مقدار پیش فرض بهوسیلۀ علامت تساوی به نام پارامتر انجام دهید.
def make_omelet2(omelet_type = "cheese"):
حال شما میتوانید این تابع را با ورودی یا بدون ورودی فراخوانی کنید.
تابع در داخل تابع
ویرایششما میتوانید تابعی را درون تابع تعریف کنید. زمانی که میخواهید تابعی بزرگ و پیچیده را به بخشهایی کوچکتر تقسیم کنید میتوانید هر یک از این بخشها را به عنوان یک تابع درون تابع اصلی تعریف کنید. در این حالت نحوۀ تعریف همانند تعریف تابع معمولی است. با این تفاوت که از بیرون تابع اصلی نمیتوان به توابع عضو دسترسی داشت.
تست پارامترها
ویرایشمتغییرها در پایتون دارای نوع ثابت نیستند و معمولاً میتوان در بازههای زمانی مختلف انواع متفاوتی از یک متغییر را داشت؛ بنابراین امکان ارسال انواع دادههایی از انواع مختلف به توابع وجود دارد. این کار ممکن است باعث بروز خطا شود یا نتایج اشتباهی را تولید کنند. برای جلوگیری از این گونه موارد باید نوع متغییر خود را قبل از استفاده در داخل تابع تست کنیم.
def make_omelet(omelet_type):
if type(omelet_type) == type({}):
print “omelet_type is a dictionary with ingredients”
return make_food(omelet_type, “omelet”)
elif type(omelet_type) == type(“”):
omelet_ingredients = get_omelet_ingredients(omelet_type)
return make_food(omelet_ingredients, omelet_type)
else:
print “I don’t think I can make this : %s” % omelet_type
در این مثال ابتدا نوع متغییر omelet_type بررسی میشود. اگر نوع آن دیکشنری باشد نشاندهندۀ مواد لازم برای تهیه غذا است پس تابع make_food با این دیکشنری و غذایی با نام omelet که به همراه آن ارسال شده فراخوانی شده و نتیجه از طریق دستور return برگشت داده میشود. در قسمت بعدی، اگر متغییر ارسالی از نوع رشته باشد فرض بر این خواهد بود که نام نوع خاصی از املت است. (elif معادل else if است). پس ابتدا از طریق تابع get_omelet_ingredients مواد لازم برای پختن آن را بهدست آورده و این مواد را همراه با نام آن به تابعی که کار درست کردن غذا را انجام میدهد، ارسال میکنیم. در بقیۀ موارد پیامی مبنی بر این که «نمیتوانیم غذای خواسته شده را درست کنیم» چاپ میکنیم!