পাইথন ডেভেলপাররা ডেকোরেটার ব্যবহার করে কোনো কলেবল ফাংশন, মেথড বা ক্লাসের আচরণ বাড়াতে বা পরিবর্তন করতে পারে, কিন্তু কলেবলটি নিজে স্থায়ীভাবে পরিবর্তন হয় না। সংক্ষেপে বলা যায়, ডেকোরেটার হলো কলেবল অবজেক্ট যা ফাংশন বা ক্লাস পরিবর্তন করতে ব্যবহৃত হয়।
ফাংশন ডেকোরেটর কী?
ফাংশন ডেকোরেটর হলো এমন ফাংশন যা আর্গুমেন্ট হিসেবে ফাংশন রেফারেন্স গ্রহণ করে, সেটার চারপাশে একটি র্যাপার যোগ করে এবং র্যাপারসহ ফাংশনটি নতুন ফাংশন হিসেবে রিটার্ন করে।
উদাহরণ দিয়ে বোঝার চেষ্টা করি:
কোড ১
@decorator
def func(arg):
return "value"
উপরের কোডটি নিচের কোডটির সমান:
কোড ২
def func(arg):
return "value"
func = decorator(func)
তাহলে দেখা যাচ্ছে, ডেকোরেটর只不过 হলো অন্য একটি ফাংশন যা একটি ফাংশন আর্গুমেন্ট হিসেবে নেয় এবং একটি ফাংশন রিটার্ন করে।
ডেকোরেটর মূলত অন্য একটি ফাংশনকে "সাজায়" বা "র্যাপ" করে এবং র্যাপ করা ফাংশন চলার আগে ও পরে কোড এক্সিকিউট করার সুযোগ দেয়। নিচের উদাহরণে এটি স্পষ্ট করা হলো:
def our_decorator(func):
def function_wrapper(x):
print("Before calling " + func.__name__)
func(x)
print("After calling " + func.__name__)
return function_wrapper
def foo(x):
print("Hi, foo has been called with " + str(x))
print("We call foo before decoration:")
foo("Hi")
print("We now decorate foo with f:")
foo = our_decorator(foo)
print("We call foo after decoration:")
foo(90)
আউটপুট
We call foo before decoration: Hi, foo has been called with Hi We now decorate foo with f: We call foo after decoration: Before calling foo Hi, foo has been called with 90 After calling foo
যদি উপরের উদাহরণটি কিছুটা জটিল লাগে, তবে সবচেয়ে সহজ ডেকোরেটর লিখতে পারি:
def null_decorator(func):
return func
উপরের null_decorator একটি কলেবল (ফাংশন), যা অন্য একটি কলেবল ইনপুট হিসেবে নেয় এবং সেটিকে কোনো পরিবর্তন ছাড়াই একই রকম রিটার্ন করে।
এখন এই সহজ ডেকোরেটরকে অন্য একটি ফাংশন ডেকোরেট (র্যাপ) করার জন্য প্রসারিত করি:
def null_decorator(func):
return func
def greet():
return "Hello, Python!"
greet = null_decorator(greet)
>>> greet()
'Hello, Python!'
উপরে আমরা একটি greet ফাংশন ডিফাইন করেছি এবং তারপর তা অবিলম্বে null_decorator ফাংশনের মাধ্যমে ডেকোরেট করেছি।
পাইথনের @ সিনট্যাক্স ব্যবহার করে উপরের প্রোগ্রামটি আরও সহজে লিখা যায় (যেখানে null_decorator-কে greet-এর ওপর স্পষ্টভাবে কল করে এবং তারপর greet ভেরিয়েবলটি পুনরায় অ্যাসাইন করার প্রয়োজন নেই):
@null_decorator
def greet():
return "Hello, Python!"
>>> greet()
'Hello, Python!'