وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

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

0 6
زمان لازم برای مطالعه: 7 دقیقه


معرفی

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

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

مفاهیم برنامه نویسی تابعی

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

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

  • توابع خالص – عوارض جانبی ندارند، یعنی حالت برنامه را تغییر نمی دهند. با توجه به ورودی یکسان، یک تابع خالص همیشه همان خروجی را تولید می کند.
  • تغییرناپذیری – داده ها را نمی توان پس از ایجاد تغییر داد. برای مثال ایجاد a را در نظر بگیرید List با 3 آیتم و ذخیره آن در یک متغیر my_list. اگر my_list تغییر ناپذیر است، شما نمی توانید موارد جداگانه را تغییر دهید. شما باید تنظیم کنید my_list به یک جدید List اگر می خواهید از مقادیر مختلف استفاده کنید.
  • توابع مرتبه بالاتر – توابع می توانند توابع دیگر را به عنوان پارامتر بپذیرند و توابع می توانند توابع جدید را به عنوان خروجی برگردانند. این به ما اجازه می‌دهد تا از اعمال خود انتزاع کنیم و در رفتار کدمان انعطاف‌پذیری به ما می‌دهد.

Haskell همچنین از طریق بارگذاری تنبل خود بر تکرارکننده ها و مولدهای پایتون تأثیر گذاشته است، اما این ویژگی برای یک زبان کاربردی ضروری نیست.

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

بدون هیچ ویژگی یا کتابخانه خاصی پایتون، می‌توانیم کدنویسی را به روشی کاربردی‌تر شروع کنیم.

توابع خالص

اگر می‌خواهید توابع خالص باشند، مقدار ورودی یا هر داده‌ای که خارج از محدوده تابع وجود دارد را تغییر ندهید.

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

بیایید یک تابع خالص برای ضرب اعداد در 2 ایجاد کنیم:

def multiply_2_pure(numbers):
    new_numbers = ()
    for n in numbers:
        new_numbers.append(n * 2)
    return new_numbers

original_numbers = (1, 3, 5, 10)
changed_numbers = multiply_2_pure(original_numbers)
print(original_numbers) 
print(changed_numbers)  

لیست اصلی از numbers بدون تغییر هستند، و ما به هیچ متغیر دیگری خارج از تابع ارجاع نمی دهیم، بنابراین خالص است.

تغییرناپذیری

تا به حال یک اشکالی داشته اید که در آن تعجب کنید که چگونه متغیری که روی 25 تنظیم کرده اید تبدیل شده است None? اگر آن متغیر تغییرناپذیر بود، خطا در جایی که متغیر در حال تغییر بود پرتاب می‌شد، نه جایی که مقدار تغییر یافته قبلاً روی نرم‌افزار تأثیر گذاشته بود – root علت اشکال را می توان زودتر پیدا کرد.

پایتون برخی از انواع داده های تغییرناپذیر را ارائه می دهد که یکی از محبوب ترین آنها است Tuple. بیایید تاپل را با یک لیست مقایسه کنیم که قابل تغییر است:

mutable_collection = ('Tim', 10, (4, 5))
immutable_collection = ('Tim', 10, (4, 5))


print(mutable_collection(2))    
print(immutable_collection(2))  


mutable_collection(1) = 15


immutable_collection(1) = 15

خطایی که مشاهده خواهید کرد این است: TypeError: 'tuple' object does not support item assignment.

حال، یک سناریوی جالب وجود دارد که در آن a Tuple ممکن است به نظر یک شیء قابل تغییر باشد. به عنوان مثال، اگر بخواهیم لیست را تغییر دهیم immutable_collection از جانب (4, 5) به (4, 5, 6)، می توانید کارهای زیر را انجام دهید:

immutable_collection(2).append(6)
print(immutable_collection(2))  

این کار می کند زیرا a List یک شیء قابل تغییر است. بیایید سعی کنیم لیست را به دوباره تغییر دهیم (4, 5).

immutable_collection(2) = (4, 5)


همانطور که انتظار داشتیم شکست می خورد. در حالی که می توانیم محتویات یک شیء قابل تغییر را در a تغییر دهیم Tuple، نمی توانیم مرجع را به شیء قابل تغییر ذخیره شده در حافظه تغییر دهیم.

پیشنهاد می‌کنیم بخوانید:  رشته های padding در پایتون

توابع مرتبه بالاتر

به یاد بیاورید که توابع مرتبه بالاتر یا یک تابع را به عنوان آرگومان می پذیرند یا یک تابع را برای پردازش بیشتر برمی گردانند. بیایید نشان دهیم که چقدر ساده می توان هر دو را در پایتون ایجاد کرد.

تابعی را در نظر بگیرید که یک خط را چندین بار چاپ می کند:

def write_repeat(message, n):
    for i in range(n):
        print(message)

write_repeat('Hello', 5)

اگر بخواهیم 5 بار در یک فایل بنویسیم، یا 5 بار پیام را وارد کنیم، چه؟ به جای نوشتن 3 تابع مختلف که همه حلقه هستند، می توانیم 1 تابع مرتبه بالاتر بنویسیم که آن توابع را به عنوان آرگومان می پذیرد:

def hof_write_repeat(message, n, action):
    for i in range(n):
        action(message)

hof_write_repeat('Hello', 5, print)


import logging

hof_write_repeat('Hello', 5, logging.error)

حال تصور کنید که ما وظیفه داریم توابعی ایجاد کنیم که اعداد را در یک لیست با 2، 5 و 10 افزایش می دهند. بیایید با مورد اول شروع کنیم:

def add2(numbers):
    new_numbers = ()
    for n in numbers:
        new_numbers.append(n + 2)
    return new_numbers

print(add2((23, 88))) 

در حالی که نوشتن پیش پا افتاده است add5 و add10 توابع، بدیهی است که آنها به همان صورت عمل می کنند: حلقه زدن لیست و اضافه کردن افزایش دهنده. بنابراین به جای ایجاد بسیاری از توابع افزایشی مختلف، 1 تابع مرتبه بالاتر ایجاد می کنیم:

def hof_add(increment):
    
    def add_increment(numbers):
        new_numbers = ()
        for n in numbers:
            new_numbers.append(n + increment)
        return new_numbers
    
    return add_increment

add5 = hof_add(5)
print(add5((23, 88)))   
add10 = hof_add(10)
print(add10((23, 88)))  

توابع سفارش بالاتر به کد ما انعطاف پذیری می دهد. با انتزاع توابع اعمال شده یا برگردانده شده، کنترل بیشتری بر رفتار برنامه خود به دست می آوریم.

پایتون چند توابع داخلی مفید برای مرتبه بالاتر ارائه می دهد که کار با دنباله ها را بسیار آسان تر می کند. ما ابتدا به عبارات لامبدا نگاه می کنیم تا بهتر از این توابع داخلی استفاده کنیم.

عبارات لامبدا

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

بیایید یک تابع سفارش بالاتر ایجاد کنیم hof_product که تابعی را برمی گرداند که یک عدد را در یک مقدار از پیش تعریف شده ضرب می کند:

def hof_product(multiplier):
    return lambda x: x * multiplier

mult6 = hof_product(6)
print(mult6(6)) 

عبارت لامبدا با کلمه کلیدی شروع می شود lambda به دنبال آرگومان های تابع. بعد از کولون، کدی است که لامبدا برگردانده است. این توانایی برای ایجاد توابع “روی the go” به‌شدت هنگام کار با عملکردهای مرتبه بالاتر استفاده می‌شود.

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

توابع سفارش بالاتر داخلی

پایتون برخی از توابع مرتبه بالاتر رایج را از زبان های برنامه نویسی تابعی پیاده سازی کرده است که پردازش اشیاء تکرارپذیر مانند لیست ها و تکرار کننده ها را بسیار آسان تر می کند. به دلایل کارایی فضا/حافظه، این توابع یک را برمی‌گردانند iterator به جای یک لیست

نقشه

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

names = ('Shivani', 'Jason', 'Yusef', 'Sakura')
greeted_names = map(lambda x: 'Hi ' + x, names)


print(greeted_names)



for name in greeted_names:
    print(name)

فیلتر کنید

را filter تابع هر عنصر را در یک شیء تکرارپذیر با تابعی که یکی را برمی گرداند، آزمایش می کند True یا False، فقط مواردی را که ارزیابی می کنند حفظ کنید True. اگر لیستی از اعداد داشتیم و می خواستیم اعدادی را که بر 5 بخش پذیر هستند نگه داریم، می توانیم موارد زیر را انجام دهیم:

numbers = (13, 4, 18, 35)
div_by_5 = filter(lambda num: num % 5 == 0, numbers)


print(list(div_by_5)) 

ترکیب کردن map و filter

از آنجایی که هر تابع یک تکرارکننده را برمی‌گرداند و هر دو اشیاء تکرارپذیر را می‌پذیرند، می‌توانیم از آنها برای دستکاری داده‌های واقعاً گویا استفاده کنیم!


arbitrary_numbers = map(lambda num: num ** 3, filter(lambda num: num % 3 == 0, range(1, 21)))

print(list(arbitrary_numbers)) 

بیان در arbitrary_numbers را می توان به 3 قسمت تقسیم کرد:

  • range(1, 21) یک شیء تکرارپذیر است که اعداد 1، 2، 3، 4… 19، 20 را نشان می دهد.
  • filter(lambda num: num % 3 == 0, range(1, 21)) یک تکرار کننده برای دنباله اعداد 3، 6، 9، 12، 15 و 18 است.
  • هنگامی که آنها توسط مکعب می شوند map عبارت ما می توانیم یک تکرار کننده برای دنباله اعداد 27، 216، 729، 1728، 3375 و 5832 دریافت کنیم.
پیشنهاد می‌کنیم بخوانید:  چرا کد پایتون در یک تابع سریعتر اجرا می شود؟

فهرست درک

یکی از ویژگی های محبوب پایتون که به طور برجسته در زبان های برنامه نویسی کاربردی ظاهر می شود، درک لیست است. مانند map و filter توابع، درک لیست به ما امکان می دهد داده ها را به روشی مختصر و رسا اصلاح کنیم.

بیایید نمونه های قبلی خود را با آن امتحان کنیم map و filter با درک لیست به جای:


names = ('Shivani', 'Jan', 'Yusef', 'Sakura')

greeted_names = ('Hi ' + name for name in names)

print(greeted_names) 

یک لیست اساسی از این قالب پیروی می کند: (نتیجه for عنصر مفرد in لیست-نام).

اگر می‌خواهیم اشیاء را فیلتر کنیم، باید از آن استفاده کنیم if کلمه کلیدی:


numbers = (13, 4, 18, 35)

div_by_5 = (num for num in numbers if num % 5 == 0)

print(div_by_5) 




arbitrary_numbers = (num ** 3 for num in range(1, 21) if num % 3 == 0)
print(arbitrary_numbers) 

هر map و filter عبارت را می توان به صورت درک لیست بیان کرد.

برخی از چیزهایی که باید در نظر بگیرید

به خوبی شناخته شده است که خالق پایتون، Guido van Rossum، قصد نداشت پایتون ویژگی های کاربردی داشته باشد، اما از برخی از مزایای معرفی آن به زبان قدردانی کرد. او تاریخچه ویژگی های زبان برنامه نویسی کاربردی را در یکی از خود مورد بحث قرار داد پست های وبلاگ. در نتیجه، پیاده سازی های زبان برای ویژگی های برنامه نویسی تابعی بهینه نشده اند.

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

در مفسر پایتون خود وارد کنید import this و “ذن پایتون” را خواهید دید. پایتون عموماً کد را تشویق می کند که به واضح ترین شکل ممکن نوشته شود. در حالت ایده‌آل، همه کدها باید به یک روش نوشته شوند – جامعه فکر نمی‌کند که باید به سبک Functional باشد.

نتیجه

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

پایتون به ما این امکان را می دهد که به سبک عملکردی و اعلانی کدنویسی کنیم. حتی از بسیاری از ویژگی‌های کاربردی رایج مانند Lambda Expressions و map و filter کارکرد.

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

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-25 01:01:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید