ارسال تابع به عنوان آرگومان
فرض کنید، فهرستی از رشتهها داریم که نام میوهها را نشان میدهند:
>>> fruits = ['kumquat', 'cherimoya', 'Loquat', 'longan', 'jujube']
اگر بخواهیم این فهرست را بر مبنای حروف الفبا مرتب کنیم، میتوانیم آن را به تابع مرتبساز داخلی منتقل کنیم:
>>> sorted(fruits)
['Loquat', 'cherimoya', 'jujube', 'kumquat', 'longan']
همانگونه که مشاهده میکنید، مرتبسازی کاملا بر مبنای حروف الفبا انجام نمیشود، زیرا وقتی پایتون رشتهها را مرتب میکند، تمام حروف بزرگ را قبل از همه حروف کوچک قرار میدهد که دلیل آن ساختار سیستم کدگذاری یونیکد و اسکی است. ما می توانیم با ارائه یک آرگومان کلیدی به تابع مرتبساز داخلی، این مشکل را برطرف کنیم.
>>> help(sorted)
sorted(iterable, /, *, key=None, reverse=False)
...
این آرگومان کلیدی باید تابعی باشد که با هر یک از آیتمهای جداگانه در فهرست میوههای فراخوانی شود تا بتواند همه عناصر را مطابق با آن چیزی که مدنظر ما قرار دارد، مرتب کند.
در مثال فوق، میتوانیم تابعی بسازیم که حروف هر رشتهای که به آن داده میشود را کوچک کند تا فرآیند مرتبسازی بر مبنای حروف کوچک انجام شود.
>>> def lowercase(string):
... return string.lower()
...
برای مرتبسازی بر اساس رشتههای کوچک، مرتبساز را با یک آرگومان کلیدی که به این تابع با حروف کوچک اشاره میکند فراخوانی میکنیم:
>>> sorted(fruits, key=lowercase)
['cherimoya', 'jujube', 'kumquat', 'longan', 'Loquat']
که به درستی فهرست رشتههای ما را بر مبنای حروف الفبا مرتب میکند، در حالی که ترکیب حروف اصلی در لیست حفظ شده است.
توجه داشته باشید که وقتی تابع مرتبساز را فراخوان میکنیم، برای فراخوانی آن، پرانتز (()) را بعد از حروف کوچک قرار ندادیم و از الگوی فراخوانی زیر استفاده کردهایم:
>>> lowercase('X')
'x'
همانگونه که دقت میکنید، ما به هیچ عنوان کاراکترهای رشته را کوچک نکردهایم و تنها به حروف کوچک اشاره کردیم:
>>> lowercase
<function lowercase at 0x7fc8a3fc09d0>
ما شی تابع با حروف کوچک را به تابع مرتبساز از طریق آرگومان کلیدی آن ارسال کردیم:
>>> sorted(fruits, key=lowercase)
به طوری که آن تابع مرتبساز میتواند خود را به طور مکرر در هر یک از آیتمهای منحصر به فرد لیست میوهها با حروف کوچک صدا بزند و با استفاده از مقدار بازگشتی که به عنوان نوعی کلید مقایسه برای مرتبسازی استفاده میشود، فرآیند مرتبسازی را به بهترین شکل انجام دهد. مثال فوق به وضوح نشان میدهد که پایتون به ما اجازه میدهد تا توابع را به عنوان عنوان آرگومان برای توابع دیگر ارسال کنیم. برای درک بهتر موضوع اجازه دهید به مثالهای دیگری اشاره کنیم.
مثال دیگری از تخصیص تابع به یک متغیر به عنوان شی
در مثال زیر یک تابع به یک متغیر اختصاص داده شده است، البته در فرآیند تخصیص فوق تابع فراخوانی نمیشود و به جای آن شی تابع اشاره شده باshout دریافت شده و و به متغیر yell تحویل داده شده و در نهایت در دستور چاپ yell پارامتر ورودی را دریافت کرده، به تابع تحویل میدهد تا به شکل حروف بزرگ کلمه hello را چاپ کند.
# Python program to illustrate functions
# can be treated as objects
def shout(text):
return text.upper()
print(shout('Hello'))
yell = shout
print(yell('Hello'))
توابع مرتبه بالاتر (Higher Order Functions)
از آنجایی که توابع اشیایی هستند، میتوانیم آنها را به عنوان آرگومان به توابع دیگر منتقل کنیم. توابعی که میتوانند توابع دیگر را به عنوان آرگومان بپذیرند، توابع مرتبه بالاتر نامیده میشوند. در مثال زیر تابعی به نام greet ایجاد میشود که تابعی را به عنوان آرگومان دریافت میکند.
# Python program to illustrate functions
# can be passed as arguments to other functions
def shout(text):
return text.upper()
def whisper(text):
return text.lower()
def greet(func):
# storing the function in a variable
greeting = func("Hi, I am created by a function passed as an argument.")
print(greeting)
greet(shout)
greet(whisper)
در قطعه کد بالا تابع shout تعریف شده که متغیری از نوع رشته را به عنوان ورودی دریافت میکند، آنرا به حروف بزرگ تبدیل میکند و به عنوان مقدار برگشتی تابع باز میگرداند.
در ادامه تابع دومی به نام whisper تعریف شده که این تابع نیز یک متغیر از نوع رشته را دریافت میکند، اما آن را به حروف کوچک تبدیل کرده و به عنوان مقدار بازگشتی تابع باز میگرداند.
تابع سوم greet نام دارد که برای دریافت توابع به عنوان آرگومان تعریف شده است. این تابع آرگومانی به نام func دارد. این متغیر قادر است دو تابع یاد شده را به عنوان آرگومان دریافت کند. همانگونه که اشاره کردیم، توابع در پایتون از نوع شی هستند، بنابراین متغیر func مشکلی در این زمینه ندارد. در ادامه متغیری به نام greeting تعریف میشود که مقدار بازگشتی تابع func را دریافت میکند که از نوع رشته است. در ادامه، دستور print مقدار greeting را چاپ میکند.
دو خط انتهایی قطعه کد بالا به ترتیب توابع shout و whisper را به عنوان متغیر دریافت میکنند. همانگونه که مشاهده میکنید، نحوه تعریف و فراخوانی تابع در پایتون سادهتر از آن چیزی است که تصور میکنید.
خروجی قطعه کد بالا به ترتیب رشته را با حروف بزرگ و سپس با حروف کوچک چاپ میکند.
تابع پوششدهنده (Wrapper function)
تابع Wrapper یا دکوراتور به ما امکان میدهد تا عملکرد تابع دیگری را گسترش دهیم، بدون آنکه تغییری در ساختار آن به وجود آوریم. در مکانیزم کاری دکوراتورها، توابع به عنوان آرگومان برای تابع دیگری ارسال میشوند و فرآیند فراخوانی در تابع wrapper انجام میشود. در زیر نمونه یک دکوراتور ساده را مشاهده میکنید.
# defining a decorator
def hello_decorator(func):
# inner1 is a Wrapper function in
# which the argument is called
# inner function can access the outer local
# functions like in this case "func"
def inner1():
print("Hello, this is before function execution")
# calling the actual function now
# inside the wrapper function.
func()
print("This is after function execution")
return inner1
# defining a function, to be called inside wrapper
def function_to_be_used():
print("This is inside the function !!")
# passing 'function_to_be_used' inside the
# decorator to control its behavior
function_to_be_used = hello_decorator(function_to_be_used)
# calling the function
function_to_be_used()
خروجی قطعه کد بالا به شرح زیر است:
Hello, this is before function execution
This is inside the function !!
This is after function execution
تابع پوششدهنده لامبدا (Lambda wrapper function)
در پایتون، تابع ناشناس (anonymous function) به این معنی است که یک تابع فاقد نام است. همانطور که میدانیم در پایتون از کلمه کلیدی def برای تعریف توابع عادی و کلمه کلیدی lambda برای ایجاد توابع ناشناس استفاده میشود. این تابع میتواند هر تعداد آرگومان داشته باشد، اما فقط قادر به دریافت یک عبارت است که ارزیابی شده و برگردانده میشود. تابع لامبدا (Lambda) میتواند تابع دیگری را به عنوان آرگومان قبول کند. مثال زیر یک تابع پایه لامبدا را نشان میدهد که در آن تابع لامبدا دیگری به عنوان آرگومان ارسال میشود.
# Defining lambda function
square = lambda x:x * x
# Defining lambda function
# and passing function as an argument
cube = lambda func:func**3
print("square of 2 is :"+str(square(2)))
print("\nThe cube of "+str(square(2))+" is " +str(cube(square(2))))
خروجی قطعه کد بالا به شرح زیر است:
square of 2 is :4
The cube of 4 is 64
کلام آخر
همانگونه که مشاهده کردید در پایتون میتوانید توابع را به عنوان آرگومان برای توابع دیگر ارسال کنید، این کار به لطف شیمحور بودن توابع امکانپذیر است. در واقع پایتون به ما اجازه میدهد فرآیند فراخوانی توابع را به سادهترین شکل انجام دهیم و یک یا چند آرگومان را به عنوان پارامتر برای توابع دیگر ارسال کنیم. همچنین، اگر به مثال اول دقت کرده باشید این تکنیک به ما اجازه میدهد از نوع خاصی از مکانیزم ساخت توابع بازگشتی به شکل پیشرفته استفاده کنیم.
ماهنامه شبکه را از کجا تهیه کنیم؟
ماهنامه شبکه را میتوانید از کتابخانههای عمومی سراسر کشور و نیز از دکههای روزنامهفروشی تهیه نمائید.
ثبت اشتراک نسخه کاغذی ماهنامه شبکه
ثبت اشتراک نسخه آنلاین
کتاب الکترونیک +Network راهنمای شبکهها
- برای دانلود تنها کتاب کامل ترجمه فارسی +Network اینجا کلیک کنید.
کتاب الکترونیک دوره مقدماتی آموزش پایتون
- اگر قصد یادگیری برنامهنویسی را دارید ولی هیچ پیشزمینهای ندارید اینجا کلیک کنید.
نظر شما چیست؟