একটি function হলো সুসংগঠিত, পুনরায় ব্যবহারযোগ্য কোডের একটি ব্লক, যা একটি নির্দিষ্ট কাজ সম্পাদন করতে ব্যবহৃত হয়।
Functions আপনার অ্যাপ্লিকেশনের জন্য আরও ভালো মডুলারিটি এবং কোড পুনরায় ব্যবহারের উচ্চ মাত্রা নিশ্চিত করে।
Python-এরও, অন্য প্রোগ্রামিং ভাষার মতো, বিল্ট-ইন ফাংশন (print, map, ইত্যাদি) রয়েছে, যা সহজেই ব্যবহার করা যায়।
আপনি নিজের ফাংশনও ডিফাইন করতে পারেন। এগুলোকে বলা হয় user-defined functions।
ফাংশন কনসোলে একটি মেসেজ প্রিন্ট করার মতো সহজ কাজও করতে পারে, আবার বেশ জটিলও হতে পারে।
একটি ফাংশনের ভেতরের কোড চালানোর জন্য আপনাকে ফাংশনটি কল করতে হবে, যা করা হয় ফাংশনের নামের পরে বন্ধনী [()] লিখে।
ডেটা, যাকে arguments বলা হয়, বন্ধনীর ভেতরে বসিয়ে ফাংশনে পাঠানো যায়।
একটি ফাংশন ডেফিনিশনে শূন্য বা তার বেশি parameters থাকতে পারে।
প্যারামিটার নির্ধারণ করে ফাংশনটি কী কী আর্গুমেন্ট গ্রহণ করবে।
একটি প্যারামিটার নির্ধারণ করে কী টাইপের আর্গুমেন্ট পাঠানো হবে।
আর্গুমেন্ট হলো ফাংশন কল করার সময় পাঠানো প্রকৃত মান।
প্যারামিটারে পাঠানো আর্গুমেন্টের উপর নির্ভর করে ফাংশন ভিন্ন ভিন্ন কাজ করতে পারে।
একটি ফাংশন return কিওয়ার্ড ব্যবহার করে একটি মান রিটার্নও করতে পারে।
ফাংশন যে মানটি রিটার্ন করে তাকে বলা হয় return value।
রিটার্ন ভ্যালু ফাংশনের কলারের কাছে ফেরত দেওয়া হয়।
Python-এ ফাংশন তৈরি করা হয় def কিওয়ার্ড ব্যবহার করে।
ফাংশন ডেফিনিশনের পরে থাকে ফাংশনের নাম এবং বন্ধনী [()]।
বন্ধনীর ভেতরে কমা দিয়ে আলাদা করে প্যারামিটারগুলো উল্লেখ করা হয়।
বন্ধনী বন্ধ করার পরে কোলন (:) দিয়ে ফাংশন সিগনেচারকে ফাংশন বডি থেকে আলাদা করা হয়।
ফাংশন বডি হলো কোডের একটি ব্লক, যা ফাংশন কল করার সময় চালানো হয়।
ফাংশনের বডি ইনডেন্ট করা থাকে।
ইনডেন্টেশন গুরুত্বপূর্ণ, কারণ কোডের ব্লকটি কোথায় শেষ হবে তা জানার জন্য Python এর উপর নির্ভর করে।
return কিওয়ার্ড ব্যবহার করে ফাংশন থেকে একটি মান রিটার্ন করা যায়, যা পরে ফাংশনের কলার ব্যবহার করতে পারে।
def function_name(parameter1, parameter2, ...):
# function body
return parameter1 + parameter2
আমরা প্যারামিটার বা রিটার্ন ভ্যালু ছাড়াও একটি ফাংশন ডিফাইন করতে পারি।
def function_name():
# function body
pass
লক্ষ্য করুন, ফাংশনের একটি বডি অবশ্যই দরকার, এমনকি বডি কিছুই না করলেও; নাহলে প্রোগ্রাম রান করার চেষ্টা করলে একটি ইনডেন্টেশন এরর তৈরি হবে:
>>> def my_bodyless_func():
...
File ~/temp.py:1
^
IndentationError: expected an indented block
একটি ফাংশন কল করতে ফাংশনের নামের পরে বন্ধনী [()] ব্যবহার করুন।
ফাংশনে পাঠানো প্যারামিটারগুলো কমা দিয়ে আলাদা করে বন্ধনীর ভেতরে বসানো হয়।
নিচের ফাংশনটি লক্ষ্য করুন:
def greet():
print("Hello")
উপরের ফাংশনটি নিচের সিনট্যাক্স ব্যবহার করে কল করা যায়:
>>> greet()
Hello
আর্গুমেন্ট হলো এমন মান, যা ফাংশন কল করার সময় সেটিতে পাঠানো হয়। এগুলো যেকোনো ডেটা টাইপের হতে পারে, এমনকি অন্য ফাংশন বা ক্লাসও।
চলুন add নামে একটি ফাংশন ডিফাইন করি, যা দুটি সংখ্যা একসাথে যোগ করে:
def add(first, second):
print(first + second)
first এবং second প্যারামিটার নির্ধারণ করে add ফাংশনটি কী কী আর্গুমেন্ট গ্রহণ করবে।
(উল্লেখ্য, parameter এবং argument শব্দ দুটি প্রায়ই একে অপরের বদলে ব্যবহৃত হয়, যদিও তা যথাযথ নয়।)
ফাংশন কল করা হলে আর্গুমেন্টগুলো ফাংশনে পাঠানো হয়।
দুটি প্যারামিটারের জন্যই আর্গুমেন্ট পাঠাতে হবে, নাহলে একটি TypeError উত্থাপিত হবে।
>>> add(2, 3)
5
# Function can be called multiple times, with different parameters
>>> add(4, 3)
7
>>> add(5, 6)
11
# Passing an incorrect number of parameters will raise a `TypeError`
>>> add(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'second'
>>> add(2, 3, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
রিটার্ন ভ্যালু হলো এমন একটি মান, যা ফাংশনের কলারের কাছে ফেরত দেওয়া হয়।
একটি return value যেকোনো ডেটা টাইপের হতে পারে, এমনকি অন্য ফাংশন বা ক্লাসও।
ফাংশনের কলার এটি ব্যবহার করে আরও কাজ করতে পারে।
কোনো ফাংশন যদি স্পষ্টভাবে একটি return value ডিফাইন না করে, তবে Python ইন্টারপ্রেটার None মানটি রিটার্ন করবে।
চলুন add নামে একটি ফাংশন ডিফাইন করি:
def add(first, second):
return first + second
আমরা রিটার্ন ভ্যালু একটি ভ্যারিয়েবলে সংরক্ষণ করে পরে তা প্রিন্ট করতে পারি:
>>> result = add(2, 3)
>>> print(result)
5
# Type of result is `int`
>>> type(result)
<class 'int'>
# We can also perform operations on the return value
>>> result * 2
10
# A function without an explicit return value will return `None`
>>> def log(message):
print(message)
# Hello is printed because of print(message), but return value is `None`
>>> return_value = log("Hello")
Hello
>>> return_value
None
return ব্যবহার করলে ফাংশনটি সঙ্গে সঙ্গে শেষ হয়ে কলারের কাছে মানটি ফেরত দেয়।
>>> def show(first, second):
print(first)
return first
print(second)
# second never gets printed, because the function exits after the return statement
>>> show(1, 2)
1
জটিল প্রোগ্রামকে ছোট ছোট অংশে ভাগ করা যায়। ভিন্ন ভিন্ন নির্দিষ্ট কাজ করতে ভিন্ন ভিন্ন ফাংশন ব্যবহার করা যায়।
ধরে নিন, একটি প্রোগ্রামকে নিচের কাজগুলো করতে হবে:
আমরা প্রোগ্রামটিকে ছোট ছোট অংশে ভাগ করতে পারি।
def circle_area(radius):
return 3.14 * radius * radius
def rectangle_area(length, breadth):
return length * breadth
def triangle_area(base, height):
return 0.5 * base * height
এখন আমরা আমাদের ইচ্ছেমতো ক্রমে ফাংশনগুলো কল করতে পারি।
>>> circle_area(2)
12.56
>>> triangle_area(2, 3)
3.0
>>> rectangle_area(2, 3)
6
>>> rectangle_area(1, 2) + circle_area(2) + triangle_area(1, 2)
15.56
কোনো ভ্যারিয়েবল (বা নাম) ফাংশনের ভেতরে ডিফাইন করা হলে তা কেবল ফাংশন স্কোপের (বা লোকাল নেইমস্পেসের) ভেতরেই অ্যাক্সেস করা যাবে, এমনকি ফাংশন স্কোপের বাইরে একই নামের ভ্যারিয়েবল থাকলেও।
ফাংশনের বাইরে মডিউল লেভেলে ডিফাইন করা ভ্যারিয়েবলকে গ্লোবাল নেইমস্পেসে ধরা হয়। ফাংশনের বাইরে কিন্তু একটি এনক্লোজিং ফাংশন বা ক্লাসের ভেতরে ডিফাইন করা ভ্যারিয়েবল থাকে ননলোকাল নেইমস্পেসে।
প্রোগ্রাম চলার সময় ভ্যারিয়েবলের নাম নির্ধারণ করতে Python LEGB নিয়ম (Local, Enclosing, Global, Built-in) ব্যবহার করে:
নাম যদি তবুও না মেলে, Python একটি NameError exception উত্থাপন করবে।
# Global namespace.
general_favorite = "apples"
def alices_favorite():
# Local namespace.
favorite = "cherries"
# This works because Python will eventually find general_favorite in the global namespace.
# Python will find 'print' in the built-in namespace.
print(f'Alice has always liked {favorite}, but most people like {general_favorite}.')
def our_favorite_fruits():
# Enclosing or nonlocal namespace.
yours = "peaches"
def my_favorite():
# Local namespace.
mine = "pears"
# This works because Python will eventually find 'yours' in the enclosing/nonlocal namespace.
print(f'My favorite is {mine}, but you like {yours} instead.')
# This works because Python will eventually find 'general_favorite' in the global namespace.
print(f'Everyone seems to like {general_favorite}')
# This function is in the local namespace of the 'our_favorite_fruits' function.
my_favorite()
# This will raise NameError: name 'favorite' is not defined, because the variable favorite is local to alices_favorite.
print(favorite)
আমরা যদি কোনো ভ্যারিয়েবলের নাম লোকাল ফাংশন স্কোপের বাইরে অ্যাক্সেসযোগ্য করতে চাই (বা ফাংশন স্কোপের বাইরে ডিফাইন করা কোনো ভ্যারিয়েবল পরিবর্তন করতে চাই), তবে global বা nonlocal কিওয়ার্ডের একটি ব্যবহার করতে হবে।
global কিওয়ার্ড ব্যবহার করলে Python ইঙ্গিত পায় খোঁজা শুরু করতে গ্লোবাল নেইমস্পেসে।
তখন ভ্যারিয়েবলে অ্যাসাইনমেন্ট লোকাল সংস্করণ তৈরি না করে গ্লোবাল ভ্যারিয়েবলটিকে পরিবর্তন করবে।
ভ্যারিয়েবল ডিক্লেয়ার করতে global ব্যবহার করলে ভ্যারিয়েবলটি গ্লোবাল নেইমস্পেসে যোগ হবে।
ফলে global সাবধানে ব্যবহার করা উচিত, কারণ একটি গ্লোবাল ভ্যারিয়েবল যোগ বা পরিবর্তন করলে তার মান ব্যবহার করে এমন সব কোডে প্রভাব পড়তে পারে।
nonlocal কিওয়ার্ড Python-কে সংকেত দেয় ভ্যারিয়েবলটি ননলোকাল বা এনক্লোজিং নেইমস্পেসে খুঁজতে বা তৈরি করতে।
এটি ব্যবহার করা হয় যখন একটি ফাংশন অন্য একটি ফাংশন বা ক্লাসের ভেতরে নেস্টেড থাকে এবং বাইরের ফাংশনের ভ্যারিয়েবল ও স্কোপে অ্যাক্সেস প্রয়োজন হয়।
Python-এ ফাংশন ভ্যারিয়েবলে অ্যাসাইন করা যায় এবং অন্য ফাংশনে আর্গুমেন্ট হিসেবে পাঠানো যায়।
এগুলো রিটার্ন ভ্যালু হিসেবেও ব্যবহার করা যায়।
ফাংশন একটি সিকোয়েন্সে (list, tuple ইত্যাদি) বা একটি dict-এর মান হিসেবেও রাখা যায়।
অন্য যেকোনো অবজেক্ট যেখানে ব্যবহার করা যায়, সেখানে ফাংশনও ব্যবহার করা যায়।
এর কারণ, ফাংশন হলো ফার্স্ট ক্লাস অবজেক্ট।
তাই এদের বিশেষ অ্যাট্রিবিউট থাকে এবং এমনকি নিজেদের কাস্টম অ্যাট্রিবিউট গেট ও সেট করার সুবিধাও ডিফাইন করতে পারে।
# print is a function
# A function can be assigned to a variable.
>>> function_as_variable = print
>>> function_as_variable("Hello")
Hello
>>> type(fake_print)
<class 'builtin_function_or_method'>
# Functions can be passed as an argument to another function.
>>> def check_print(func):
func("Hello")
>>> check_print(print)
Hello
# Function can be used as an item in a sequence.
>>> my_list = [print, "Hello"]
>>> my_list[0]("Hello")
Hello
# Functions can be used as a value in a dictionary.
>>> my_dict = {"key": print}
>>> my_dict["key"]("Hello")
Hello
# Functions can be returned from a function.
>>> def return_func():
return print
>>> return_func()("Hello")
Hello
ফাংশন অন্য ফাংশনের ভেতরে নেস্টেডও থাকতে পারে।
def outer():
num = 10
# This is a nested, or "inner" function.
def inner():
print(num)
# Outer function calling inner function
inner()
ইনার ফাংশন বাইরের ফাংশনে ডিফাইন করা num ভ্যারিয়েবলটি অ্যাক্সেস করতে পারে।
>>> outer()
10
Python-এ ফাংশনের বিশেষ কিছু অ্যাট্রিবিউট থাকে। সেগুলোর কয়েকটি হলো:
__name__: ফাংশনের নাম__doc__: ফাংশনের ডকুমেন্টেশন স্ট্রিং__module__: যে মডিউলে ফাংশনটি ডিফাইন করা হয়েছে__globals__: ফাংশনের গ্লোবাল ভ্যারিয়েবলগুলোর ডিকশনারি__code__: ফাংশনের নির্দেশনা ধারণ করা কোড অবজেক্ট>>> def add(first, second):
return first + second
# Function name
>>> print.__name__
'print'
>>> len.__name__
'len'
>>> add.__name__
'add'
# Function documentation
>>> abs.__doc__
'Return the absolute value of the argument.'
# Module
>>> len.__module__
'builtins'
>>> add.__module__
'__main__'
ফাংশন অ্যাট্রিবিউটের সম্পূর্ণ তালিকা পাওয়া যাবে Python ডেটা মডেল-এ।