مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

ترجمه و تالیف : علیرضا معمارزاده
تاریخ انتشار : 30 بهمن 98
خواندن در 4 دقیقه
دسته بندی ها : پایتون

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

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

توابع First-Class

توابع، در پایتون first-class هستند؛ به این معنی که می‌توان آن‌ها را فقط به‌عنوان یک نوع داده دیگر مثل int درنظر گرفت.

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

توابع در قالب شی

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

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

ازآنجایی‌که توابع، شیء هستند، می‌توان تابع foo را به هر متغیری اختصاص داد و سپس آن متغیر را برای ارجاع دادن به تابع فراخوانی کرد. برای مثال، می‌توان آن را به متغیر bar به‌صورت زیر اختصاص داد:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

عبارت bar = foo، شی که foo (نام تابع ما) به آن ارجاع می‌دهد را به متغیر bar اختصاص می‌دهد.

شیء در قالب توابع

شیء می‌تواند مثل توابع عمل کنند زمانی که آن‌ها را قابل فراخوانی تعریف می‌کنیم مثل: object(). این روش با استفاده از متد  __call__انجام می‌شود.

به مثال زیر توجه کنید:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

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

به مثال زیر توجه کنید:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

چون ما متد __call__ را در تعریف کلاس داشتیم، توانستیم شیء morning را فراخوان کنیم. برای تشخیص اینکه یک شیء قابل فراخوانی هست یا نه از تابع callable همانند مثال زیر استفاده می‌کنیم:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

توابع داخل ساختار داده

توابع، مانند سایر اشیاء می‌توانند داخل ساختار داده ذخیره شوند. برای مثال، ما می‌توانیم یک دیکشنری از int به func بسازیم. این، زمانی بکار می‌آید که int قسمت کوچکی از روش درحال اجرا باشد.

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

به‌صورت مشابه، توابع می‌توانند در سایر ساختارهای داده ذخیره شوند.

توابع در قالب آرگومان‌ها و مقادیر بازگشتی

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

توابع سطح بالا بسیار قدرتمند هستند و به‌خوبی در Eloquent JavaScript تعریف شده‌اند:

«توابع سطح بالا به ما کمک می‌کنند که نه‌تنها مقادیر بلکه عملیات را خلاصه کنیم.»

مثال زیر را در نظر بگیرید.

می‌خواهیم فهرستی از موارد را تکرار و سپس آن‌ها را چاپ کنیم. به‌راحتی می‌توانیم یک تابع iterate بسازیم:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

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

اینجاست که توابع سطح بالا مورداستفاده قرار می‌گیرند. می‌توانیم یک تابع iterate_custom ایجاد کنیم که هم فهرست را تکرار می‌کند و هم یک تابع به هرکدام از موارد اضافه می‌کند همانند مثال زیر:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

اگرچه ممکن است چندان مهم به نظر نرسد، اما بسیار قدرتمند است.

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

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

به‌عنوان‌مثال:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

توابع تودرتو

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

توابع کمکی زمانی کاربردی هستند که مسئله‌ای نیاز به تعریف یک تابع خاص داشته باشد (آرگومان یا دستور) اما حل مسئله بدون پیروی از مقررات آسان‌تر باشد. 

بیاید یه مثال خوب دراین زمینه بزنیم:

فرض می‌کنیم که شما می‌خواهید یک تابع فیبوناچی fib(n)  تعریف کنید که یک آرگومان n دارد و باید nامین عدد فیبوناچی را برگردانیم.

یک راه ممکن برای تعریف چنین تابعی استفاده از توابع کمکی است که دو عبارت قبلی دنباله فیبوناچی را دنبال می‌کند (چون هر عدد فیبوناچی، مجموع دو عدد قبلی آن است).

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

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

لامبدا (Lambda)

چگونه می‌توانیم یک تابع بدون اختصاص نام به آن بنویسیم؟ چگونه می‌توان یک تابع کوتاه یک‌خطی (مثل توابع foo یا mult در مثال‌های بالا) نوشت؟

می‌توان از lambda برای تعریف چنین توابعی در پایتون استفاده کرد. به‌عنوان‌مثال:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

رفتار تابع mult دقیقاً شبیه تابعی است که قبلاً با استفاده از def تعریف کردیم.

توجه داشته باشید که توابع lambda باید یک‌خطی باشند و نباید شامل یک عبارت بازگشتی که توسط برنامه‌نویس نوشته شده است، باشند.

درواقع، آن‌ها همیشه یک عبارت ضمنی بازگشتی دارند (در مثال بالا، گفته می‌شود: return x * y؛ اما ما عبارات ضمنی بازگشتی را از تابع lambda حذف می‌کنیم).

تابع lambda خیلی قدرتمند و کوتاه است چون با استفاده از آن می‌توان توابع بدون نام ایجاد کرد:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

این روش برای زمانی مفید است که فقط یک‌بار به یک تابع نیاز داریم و بعداً استفاده‌ای از آن نمی‌کنیم. به‌عنوان‌مثال، زمانی که یک دیکشنری را کامل می‎‌کنیم:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

اکنون می‌توانیم به توابع Map، Filter و Reduce نگاه کنیم و بیشتر از قبل از روش lambda قدردانی کنیم.

تابع Map

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

به‌عنوان‌مثال:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

در پایتون 3، تابع map یک شیء map را بازمی‌گرداند و می‌تواند تبدیل به یک لیست شود تا بتوانیم از آن استفاده کنیم. اکنون به‌جای تعریف تابع جداگانه multiply_by_four، می‌توانیم یک lambda تعریف کنیم:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

می‌توانید مشاهده کنید که 4 خط کد بالا را در 1 خط خلاصه کردیم و این واقعاً عالی است.

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

تابع Filter

Filter همان‌طور که از اسمش پیداست، تابعی است که به فیلتر کردن مواردی که نیاز به آن‌ها نداریم، کمک می‌کند. به‌عنوان‌مثال، ممکن است بخواهیم تمام اعداد فرد را از scores حذف کنیم. می‌توان این کار را با استفاده از filter انجام داد:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

ازآنجاکه نحوه عملکرد این تابع به این صورت است که مورد به مورد برای پذیرش هر آیتم تصمیم‌گیری می‌کند، باید مقدار bool را (که در تابع lambda مثال بالا هم دیده می‌شود)، برگرداند و یکنواخت باشد (یک ورودی پارامتری دریافت کند).

تابع Reduce

Reduce تابعی برای خلاصه‌سازی یا گرفتن یک تصویر بزرگ از مجموعه‌ای از داده‌هاست. به‌عنوان‌مثال، اگر بخواهیم جمع تمام نمرات را حساب کنیم، باید از reduce استفاده کنیم:

مقدمه‌ای بر برنامه‌نویسی تابع محور در پایتون

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

کلام آخر

ما در این مقاله برنامه نویسی تابعی رو مورد بررسی قرار دادیم. توجه داشته باشید که مطالب بالا به شما برای شروع کار برنامه‌نویسی در پایتون کمک می‌کنند. برای اطلاعات بیشتر می‌توانید به مقالات زیر مراجعه کنید:

اهمیت برنامه‌نویسی تابعی در پایتون

برنامه‌نویسی تابعی دقیقا چیست؟

مقدمه‌ای بر برنامه‌نویسی تابعی در پایتون

منبع

گردآوری و تالیف علیرضا معمارزاده
آفلاین
user-avatar

Student of Software Engineering, python Developer, i love programming and game

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید