Decorators in Python in Hindi
मौजूदा कोड में कार्यक्षमता जोड़ने के लिए Decorators in Python नामक एक दिलचस्प विशेषता है।
इसे metaprogramming भी कहा जाता है क्योंकि प्रोग्राम का एक हिस्सा संकलन समय पर प्रोग्राम के दूसरे हिस्से को संशोधित करने का प्रयास करता है।
Prerequisites for learning decorators in python
decorators के बारे में समझने के लिए, हमें पहले पायथन में कुछ बुनियादी बातें जाननी चाहिए।
हमें इस तथ्य से सहज होना चाहिए कि पायथन में सब कुछ (हाँ! यहां तक कि कक्षाएं), वस्तुएं हैं। जिन नामों को हम परिभाषित करते हैं वे केवल इन वस्तुओं से बंधे हुए पहचानकर्ता हैं। कार्य कोई अपवाद नहीं हैं, वे वस्तुएं भी हैं (विशेषताओं के साथ)। कई अलग-अलग नाम एक ही फ़ंक्शन ऑब्जेक्ट से बंधे हो सकते हैं।
Example for decorators in Python
def first(msg):
print(msg)
first("Hello")
second = first
second("Hello")
जब आप कोड चलाते हैं, तो first
& second
दोनों कार्य समान आउटपुट देते हैं। यहां, first
& second
नाम एक ही फ़ंक्शन ऑब्जेक्ट को संदर्भित करते हैं।
अब चीजें अजीब होने लगी हैं।
फ़ंक्शन को किसी अन्य फ़ंक्शन के तर्क के रूप में पारित किया जा सकता है।
यदि आपने पायथन में map
, filter
और reduce
जैसे कार्यों का उपयोग किया है, तो आप इसके बारे में पहले से ही जानते हैं।
ऐसे फलन जो अन्य कार्यों को तर्क के रूप में लेते हैं, higher order functions कहलाते हैं। यहाँ इस तरह के एक समारोह का एक उदाहरण है।
def inc(x):
return x + 1
def dec(x):
return x - 1
def operate(func, x):
result = func(x)
return result
हम फ़ंक्शन को निम्नानुसार आमंत्रित करते हैं।
>>> operate(inc,3)
4
>>> operate(dec,3)
2
इसके अलावा, एक फ़ंक्शन दूसरे फ़ंक्शन को वापस कर सकता है।
def is_called():
def is_returned():
print("Hello")
return is_returned
new = is_called()
# Outputs "Hello"
new()
यहाँ, is_returned () एक नेस्टेड फ़ंक्शन है जिसे परिभाषित किया जाता है और हर बार जब हम is_called () कहते हैं, तो उसे लौटा दिया जाता है।
Getting back to Decorators in Python in Hindi
कार्यों और विधियों को कॉल करने योग्य (callable)कहा जाता है क्योंकि उन्हें बुलाया जा सकता है।
वास्तव में, कोई भी वस्तु जो विशेष __call__() विधि को लागू करती है उसे कॉल करने योग्य कहा जाता है। तो, सबसे बुनियादी अर्थों में, एक डेकोरेटर एक कॉल करने योग्य है जो कॉल करने योग्य देता है।
मूल रूप से, एक डेकोरेटर एक फ़ंक्शन लेता है, कुछ कार्यक्षमता जोड़ता है और उसे वापस करता है।
def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")
जब आप शेल में निम्न कोड चलाते हैं,
>>> ordinary()
I am ordinary
>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary
ऊपर दिखाए गए उदाहरण में, make_pretty() एक डेकोरेटर है। असाइनमेंट चरण में
pretty = make_pretty(ordinary)
ordinary()
फ़ंक्शन को सजाया गया और लौटाए गए फ़ंक्शन को सुंदर नाम दिया गया।
हम देख सकते हैं कि decorator function ने मूल फ़ंक्शन में कुछ नई कार्यक्षमता जोड़ी है। यह उपहार पैक करने के समान है। डेकोरेटर एक आवरण के रूप में कार्य करता है। सजाई गई वस्तु की प्रकृति (अंदर वास्तविक उपहार) नहीं बदलती है। लेकिन अब, यह सुंदर लग रहा है (क्योंकि इसे सजाया गया है)।
आम तौर पर, हम एक फ़ंक्शन को सजाते हैं और इसे पुन: असाइन करते हैं,
ordinary = make_pretty(ordinary).
यह एक सामान्य निर्माण है और इस कारण से, इसे सरल बनाने के लिए पायथन के पास एक सिंटैक्स है।
हम डेकोरेटर फंक्शन के नाम के साथ @ सिंबल का उपयोग कर सकते हैं और इसे डेकोरेटेड फंक्शन की परिभाषा के ऊपर रख सकते हैं। उदाहरण के लिए,
@make_pretty
def ordinary():
print("I am ordinary")
के बराबर है
def ordinary():
print("I am ordinary")
ordinary = make_pretty(ordinary)
सज्जाकारों को लागू करने के लिए यह सिर्फ एक वाक्यात्मक चीनी है।
Decorating Functions in Python with Parameters
उपरोक्त डेकोरेटर सरल था और यह केवल उन कार्यों के साथ काम करता था जिनमें कोई पैरामीटर नहीं था। क्या होगा यदि हमारे पास ऐसे कार्य हैं जो पैरामीटर में लेते हैं जैसे:
def divide(a, b):
return a/b
इस फ़ंक्शन के दो पैरामीटर हैं, a और b। हम जानते हैं कि यदि हम b को 0 के रूप में पास करते हैं तो यह एक त्रुटि देगा।
>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
अब इस मामले की जांच के लिए एक डेकोरेटर बनाते हैं जो त्रुटि का कारण बनेगा।
def smart_divide(func):
def inner(a, b):
print("I am going to divide", a, "and", b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a, b)
return inner
@smart_divide
def divide(a, b):
print(a/b)
त्रुटि की स्थिति उत्पन्न होने पर यह नया कार्यान्वयन कोई नहीं लौटाएगा।
>>> divide(2,5)
I am going to divide 2 and 5
0.4
>>> divide(2,0)
I am going to divide 2 and 0
Whoops! cannot divide
इस तरह, हम उन कार्यों को सजा सकते हैं जो पैरामीटर लेते हैं।
एक उत्सुक पर्यवेक्षक यह नोटिस करेगा कि डेकोरेटर के अंदर नेस्टेड inner()
फ़ंक्शन के पैरामीटर उसी तरह के फ़ंक्शन के पैरामीटर हैं जो इसे सजाते हैं। इसे ध्यान में रखते हुए, अब हम सामान्य सज्जाकार बना सकते हैं जो किसी भी संख्या में मापदंडों के साथ काम करते हैं।
पायथन में, यह जादू function(*args, **kwargs)
के रूप में किया जाता है। इस तरह, args स्थितीय तर्कों का टपल होगा और kwargs
कीवर्ड तर्कों का शब्दकोश होगा। ऐसे डेकोरेटर का एक उदाहरण होगा:
def works_for_all(func):
def inner(*args, **kwargs):
print("I can decorate any function")
return func(*args, **kwargs)
return inner
Chaining Decorators in Python
पायथन में कई डेकोरेटर्स को chained में बांधा जा सकता है।
कहने का तात्पर्य यह है कि एक समारोह को अलग-अलग (या समान) सज्जाकारों के साथ कई बार सजाया जा सकता है। हम केवल डेकोरेटर्स को वांछित फ़ंक्शन के ऊपर रखते हैं।
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
def percent(func):
def inner(*args, **kwargs):
print("%" * 30)
func(*args, **kwargs)
print("%" * 30)
return inner
@star
@percent
def printer(msg):
print(msg)
printer("Hello")
OUTPUT :-
syntax :-
@star
@percent
def printer(msg):
print(msg)
के बराबर है
def printer(msg):
print(msg)
printer = star(percent(printer))
जिस क्रम में हम डेकोरेटर्स को चेन करते हैं वह मायने रखता है। अगर हमने आदेश को उलट दिया होता,
@percent
@star
def printer(msg):
print(msg)