Python को एक शक्तिशाली प्रोग्रामिंग भाषा बनाने वाले कारकों में से एक है इसके magic methods। कुछ Pythonista समूहों में, इनके डबल अंडरस्कोर स्वरूप के कारण इन्हें ‘dunder methods’ भी कहा जाता है।
Python में इनका कार्य ‘operator overloading’ नामक प्रक्रिया को निष्पादित करना है, जिसका सीधा अर्थ है किसी पूर्वपरिभाषित ऑपरेटर को विस्तारित अर्थ देना। दूसरे शब्दों में, ऑपरेटर ओवरलोडिंग का उपयोग हमारी कक्षाओं (classes) में कस्टम व्यवहार जोड़ने के लिए किया जाता है ताकि वे Python के ऑपरेटरों और इन-बिल्ट कार्यक्षमताओं के साथ उपयोग योग्य बनें।
इस लेख में, हम Python magic methods को गहराई से समझेंगे, जिसके तहत हम:
मेथड्स और फंक्शंस के बीच का अंतर स्पष्ट करेंगे
समझाएँगे कि magic methods क्या होते हैं
कुछ Python उदाहरण देंगे।
इस ट्यूटोरियल में प्रयुक्त कोड को फॉलो करने के लिए यह DataLab वर्कबुक देखें।
Python Methods बनाम Functions
यह समझने से पहले कि magic methods क्या हैं, हमें Python में मेथड और फंक्शन के बीच का अंतर जानना होगा।
Python किसी ऑब्जेक्ट के व्यवहार का निरूपण करने के लिए methods का उपयोग करता है। इस प्रकार, methods किसी ऑब्जेक्ट से संबद्ध होते हैं और उस ऑब्जेक्ट के भीतर मौजूद डेटा पर कुछ ऑपरेशन करते हैं। किसी method की एक और महत्वपूर्ण पहचान self पैरामीटर है, जो हमेशा method को पास किए जाने वाला पहला पैरामीटर होता है।
ध्यान दें: पहले पैरामीटर के रूप में शब्द self होना अनिवार्य नहीं है, लेकिन Pythonistas ने सार्वभौमिक रूप से इसे सर्वोत्तम प्रथा माना है।
# Example of a methodclassHuman:# This is a methoddefwalk(self):print("I am walking")संचालित द्वारा
Methods उस class पर निर्भर होते हैं जिनसे वे संबद्ध हैं। इसलिए, किसी method को कॉल करने के लिए, डॉट ऑपरेटर से method तक पहुँचने से पहले class का एक instance बनाना आवश्यक है।
# This will work
joe = Human()
joe.walk()"""
I am walking
"""# This will throw a NameError
walk()---------------------------------------------------------------------------
NameError Traceback (most recent call last)/tmp/ipykernel_153/2327344440.py in<module>45# This will throw a NameError---->6 walk()
NameError: name 'walk'isnot definedसंचालित द्वारा
दूसरी ओर, एक function अलग होता है: हमें class का instance बनाने की आवश्यकता नहीं होती।
Python functions कोड के ब्लॉक के रूप में परिभाषित चरण होते हैं, जो केवल कॉल किए जाने पर निष्पादित होते हैं। वे किसी भी class ऑब्जेक्ट से स्वतंत्र रूप से परिभाषित होते हैं, यानी उन्हें सीधे उनके नाम से कॉल किया जा सकता है। चूँकि वे किसी class से संबद्ध नहीं हैं, हमें self पैरामीटर पास करने की ज़रूरत नहीं होती – पैरामीटर्स वैकल्पिक होते हैं।
मूल रूप से, एक function बस सुव्यवस्थित निर्देशों का समूह होता है जिसका उपयोग इंटरप्रेटर किसी कार्य को करने के लिए करता है।
# Example of a functiondefrun():print("I am running.")
run()"""
I am running.
"""संचालित द्वारा
हमारे How to call and write functions लेख में विस्तार से बताया गया है कि functions दो प्रकार के होते हैं: बिल्ट-इन और यूज़र-परिभाषित।
Built-in functions: वे फंक्शंस जो Python की स्टैंडर्ड लाइब्रेरी में शामिल होते हैं।
User-defined functions: वे फंक्शंस जो उपयोगकर्ता द्वारा परिभाषित किए जाते हैं - Python उपयोगकर्ताओं को अपने स्वयं के फंक्शंस परिभाषित करने और उन्हें Python प्रोग्राम में एक्सेस करने की अनुमति देता है।
कई मायनों में, methods और functions समान हैं - यानी दोनों def स्टेटमेंट से परिभाषित होते हैं। मुख्य अंतर यह है कि methods किसी ऑब्जेक्ट से संबद्ध होते हैं और class के भीतर निहित डेटा पर काम करने के लिए उपयोग किए जाते हैं, जबकि functions स्वतंत्र रूप से परिभाषित होते हैं और प्रोग्राम में कहीं भी नाम से कॉल किए जा सकते हैं।
Python magic methods क्या हैं?
ट्यूटोरियल की शुरुआत में, हमने बताया था कि डबल अंडरस्कोर स्वरूप के कारण magic methods को dunder methods भी कहा जाता है। हमारा अभिप्राय यह था कि सभी Python magic methods दो अंडरस्कोर से शुरू होते और समाप्त होते हैं।
सबसे प्रसिद्ध magic method __init__ है, जो किसी class को विशिष्ट गुणों (attributes) के साथ इनिशियलाइज़ करने में सक्षम बनाता है।
classEmployee:def__init__(self, name, age, role):
self.name = name
self.age = age
self.role = roleसंचालित द्वारा
इस class का instance बनाने के लिए, हमें instance के name, age, और role गुणों को निर्दिष्ट करना होगा। उदाहरण के लिए:
user_1 = Employee(name="John", age=24, role="Data Scientist")संचालित द्वारा
__init__ method इनिशियलाइज़ेशन और कंस्ट्रक्शन magic methods की श्रेणी में आता है, पर यह अकेला नहीं है। नीचे दी गई तालिका में कुछ अन्य इनिशियलाइज़ेशन और कंस्ट्रक्शन magic methods दिए गए हैं।
__new__(cls, other)
किसी class का नया instance बनाने के लिए उपयोग किया जाता है
__init__(self, other)
नया instance बनने के बाद कॉल होता है; class कंस्ट्रक्टर अभिव्यक्ति को पास किए गए सभी गुण attributes के रूप में उपयोग किए जाएँगे।
__del__(self)
डिस्ट्रक्टर के रूप में भी जाना जाता है; instance के नष्ट किए जाने पर कॉल होता है।
Magic methods को समझने का सबसे सरल तरीका यह मानना हो सकता है कि ये आपके इम्प्लीमेंटेशन और Python इंटरप्रेटर के बीच एक अनुबंध हैं। इस अनुबंध की एक शर्त यह है कि कुछ परिस्थितियों में Python पर्दे के पीछे कुछ क्रियाएँ करेगा, जैसे किसी class instance को विशिष्ट ऑब्जेक्ट्स के साथ इनिशियलाइज़ करना।
दूसरे शब्दों में, किसी magic method को सीधे कॉल करना आपकी ज़िम्मेदारी नहीं है - Python इसे पर्दे के पीछे अपने आप निष्पादित करता है।
स्ट्रिंग रिप्रेज़ेंटेशन methods
Python एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) भाषा है – Python में हर चीज़ एक ऑब्जेक्ट है। जब एक नया ऑब्जेक्ट बनाया जाता है, तो हम अप्रत्यक्ष रूप से एक सम्बद्ध ऑब्जेक्ट भी बनाते हैं क्योंकि सभी classes object से इनहेरिट करती हैं।
टिप्पणी: आप अपने class को परिभाषित करते समय class object पास करके इनहेरिटेंस को स्पष्ट भी कर सकते हैं।
# This worksclassCar:pass
# This also worksclassVehicle(object):pass
car = Car()
vehicle = Vehicle()
print(car, vehicle, sep="\n")"""
<__main__.Car object at 0x7f80449dc0a0>
<__main__.Vehicle object at 0x7f80449dc1f0>
"""संचालित द्वारा
ऊपर दिए गए कोड में, हमने दो खाली classes बनाई हैं, फिर भी जब हमने print स्टेटमेंट चलाया, तो Python इंटरप्रेटर को पता था कि क्या प्रिंट करना है। यह संभव है क्योंकि सभी classes object class (Python में सभी classes की पैरेंट) से इनहेरिट करती हैं, और उसमें __repr__ नामक एक magic method होता है, जिसे print स्टेटमेंट वैल्यू लौटाने के लिए कॉल करता है।
जो पाठक इनहेरिटेंस से परिचित हैं, वे जानते होंगे कि एक चाइल्ड class अपने पैरेंट class के method को उसी नाम का अपना method परिभाषित करके ओवरराइड कर सकता है।
# Overriding the object __repr__classVehicle:def__repr__(self):returnf"{self.__class__.__qualname__}"
vehicle = Vehicle()print(vehicle)"""
Vehicle
"""संचालित द्वारा
आप __str__ magic method का भी उपयोग कर सकते हैं ताकि print स्टेटमेंट के साथ कॉल होने वाली स्ट्रिंग रिप्रेज़ेंटेशन बनाई जा सके।
वास्तव में, __repr__ magic method, __str__ magic method के बैकअप व्यवहार के रूप में कार्य करता है। इसलिए, जब हम print स्टेटमेंट कॉल करते हैं, तो Python पहले आपकी class में परिभाषित __str__ method को ढूँढता है और उसके न मिलने पर __repr__ method पर वापस जाता है।
# Using __str__ for string representationclassVehicle:def__str__(self):returnf"{self.__class__.__qualname__}"
vehicle = Vehicle()print(vehicle)"""
Vehicle
"""संचालित द्वारा
नीचे दी गई तालिका में अन्य स्ट्रिंग रिप्रेज़ेंटेशन magic methods की सूची दी गई है।
__str__(self)
Python के इन-बिल्ट str() फंक्शन और print स्टेटमेंट द्वारा किसी ऑब्जेक्ट की अनौपचारिक स्ट्रिंग रिप्रेज़ेंटेशन दिखाने के लिए कॉल किया जाता है। ध्यान दें कि इसके लिए वैध Python अभिव्यक्ति होना आवश्यक नहीं है।
__repr__(self)
Python के इन-बिल्ट repr() फंक्शन और स्ट्रिंग कन्वर्ज़न द्वारा किसी ऑब्जेक्ट की आधिकारिक स्ट्रिंग रिप्रेज़ेंटेशन दिखाने के लिए कॉल किया जाता है। ध्यान दें कि यह एक वैध Python अभिव्यक्ति जैसा दिखना चाहिए, लेकिन यदि यह संभव न हो तो उपयोगी विवरण वाली स्ट्रिंग को प्राथमिकता दी जाती है।
__unicode__(self)
Python के इन-बिल्ट unicode() फंक्शन को इम्प्लीमेंट करने के लिए कॉल किया जाता है और यह एक Unicode ऑब्जेक्ट लौटाता है।
__hash__(self)
Python के इन-बिल्ट hash() फंक्शन और hashed कलेक्शनों के सदस्यों पर किए जाने वाले ऑपरेशंस द्वारा कॉल किया जाता है। यह method एक पूर्णांक लौटाना चाहिए।
__nonzero__(self)
Python के इन-बिल्ट bool() ऑपरेशन द्वारा सत्यता जाँच (truth value testing) को लागू करने के लिए कॉल किया जाता है। यह method True या False (या उनके पूर्णांक समतुल्य 1 या 0) लौटाना चाहिए।
एन्कैप्सुलेशन के “magic” methods
एन्कैप्सुलेशन ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) की मूलभूत अवधारणाओं में से एक है। यह डेटा और उस डेटा पर काम करने वाले methods को एक साथ बाँधने या किसी ऑब्जेक्ट के भीतर कुछ कॉम्पोनेन्ट्स तक सीधे एक्सेस को प्रतिबंधित करने को संदर्भित करता है।
अन्य OOP भाषाओं से आने वाले डेवलपर्स अक्सर यह तर्क देते हैं कि Python कक्षाओं के लिए एन्कैप्सुलेशन को सच में अपनाने में असफल रहा है। ये लोग methods या फ़ील्ड्स के लिए स्पष्ट मॉडिफ़ायर्स के आदी होते हैं जो उन्हें पब्लिक गेटर्स और सेटर्स के साथ प्राइवेट एट्रिब्यूट्स जैसी चीज़ें परिभाषित करने में सक्षम बनाते हैं। Python में अंतर यह है कि एन्कैप्सुलेशन का बहुत सा भाग magic methods के माध्यम से होता है।
उदाहरण के लिए, __setattr__ एक एन्कैप्सुलेशन समाधान है जो हमें किसी एट्रिब्यूट को असाइन करते समय (चाहे वह मौजूद हो या नहीं) व्यवहार परिभाषित करने में सक्षम बनाता है। दूसरे शब्दों में, एट्रिब्यूट्स के मानों में बदलाव के लिए नियम परिभाषित किए जा सकते हैं।
import string
classAlphabet():def__setattr__(self, name, value):
self.__dict__[name]= value.upper()
a = Alphabet()# Assinging an attribute that does not exist# The setattr should convert it to caps despite being set as lowercase
a.alphabet = string.ascii_lowercase
print(a.alphabet)संचालित द्वारा
ऊपर दिए गए कोड में, हमने Alphabet नामक एक class बनाई जिसके कोई एट्रिब्यूट्स नहीं हैं, लेकिन हमने Python को यह बताया कि class instance के किसी भी एट्रिब्यूट को सेट करते समय उसे कैपिटल में बदलना है।
हम समझते हैं कि कुछ पाठकों के लिए OOP थोड़ी दूर की चीज़ हो सकती है। Python में OOP पर पकड़ मज़बूत करने के लिए DataCamp का Python Programmer Track देखें।
Math magic methods
Python magic methods की एक और श्रेणी गणितीय magic methods हैं (जिन्हें सामान्य arithmetic ऑपरेटर्स भी कहा जाता है)। Python में अभिव्यक्तियाँ विशेष प्रतीकों, यानी ‘ऑपरेटर्स’ का उपयोग करके बनाई जाती हैं। किसी अभिव्यक्ति में ऐसे ऑपरेटर्स का उपयोग करने का अर्थ उन ऑब्जेक्ट्स का निर्माण करना है जिनमें संबंधित math magic methods हों। ऐसा न करने पर TypeError उत्पन्न होगी।
classNumbers:def__init__(self, a, b):
self.a = a
self.b = b
set_a = Numbers(2,4)
set_b = Numbers(3,5)
print(set_a + set_b)"""
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_152/3639634723.py in <module>
7 set_b = Numbers(3, 5)
8
----> 9 print(set_a + set_b)
TypeError: unsupported operand type(s) for +: 'Numbers' and 'Numbers'
"""संचालित द्वारा
ऊपर दिए गए कोड में, हमने Numbers class के कई instances बनाने और उन्हें आपस में जोड़ने का प्रयास किया, जिससे अपेक्षित रूप से त्रुटि आई। इस त्रुटि का एक समाधान यह हो सकता है कि हम अपनी class में नंबर जोड़ने के लिए कोई method बनाएँ, लेकिन इससे हम अभिव्यक्तियाँ (expressions) बनाने से वंचित रहेंगे।
एक बेहतर समाधान __add__ magic method को निम्नानुसार इम्प्लीमेंट करना होगा:
# Using add operatorclassNumbers:def__init__(self, a, b):
self.a = a
self.b = b
def__add__(self, other):# Only permit Numbers objects to be addedifnotisinstance(other, Numbers):return NotImplemented
return Numbers(other.a + self.a, other.b + self.b)def__repr__(self):returnf"{self.__class__.__qualname__}({self.a}, {self.b})"
a = Numbers(2,4)
b = Numbers(3,5)print(a + b)# Should result in Numbers(5, 9)"""
RandomNumbers(5, 9)
"""संचालित द्वारा
ऊपर दिए गए कोड उदाहरण में हम केवल दो Numbers ऑब्जेक्ट्स को आपस में जोड़ सकते हैं। आइए एक और math magic method इम्प्लीमेंट करें जो हमें किसी Numbers ऑब्जेक्ट को एक पूर्णांक से गुणा करने की अनुमति दे।
# Multiplying Numbers with an integerclassNumbers:def__init__(self, a, b):
self.a = a
self.b = b
def__add__(self, other):# Only permit Numbers objects to be addedifnotisinstance(other, Numbers):return NotImplemented
return Numbers(other.a + self.a, other.b + self.b)def__mul__(self, other):ifnotisinstance(other,int):return NotImplemented
return Numbers(self.a * other, self.b * other)def__repr__(self):returnf"{self.__class__.__qualname__}({self.a}, {self.b})"
a = Numbers(2,4)print(a *5)# Should return 10, 20"""
RandomNumbers(10, 20)
"""संचालित द्वारा
ऊपर दिए गए कोड में, हमने __mul__ magic method जोड़ा ताकि हम अपनी कस्टम class के नंबरों को किसी पूर्णांक से गुणा कर सकें।
ध्यान दें कि Numbers ऑब्जेक्ट * ऑपरेटर के बाएँ तरफ है - यह संयोग नहीं है। आइए इसे ऑपरेटर के दाएँ तरफ रखें और देखें क्या होता है।
- snip --
a = Numbers(2,4)print(3* a)---------------------------------------------------------------------------
TypeError Traceback (most recent call last)/tmp/ipykernel_152/2857655049.py in<module>1 a = Numbers(2,4)---->2print(3* a)
TypeError: unsupported operand type(s)for*:'int'and'Numbers'संचालित द्वारा
Python एक TypeError फेंकता है।
हमारे द्वारा इम्प्लीमेंट किया गया __mul__ magic method केवल तब काम करता है जब Numbers ऑब्जेक्ट * ऑपरेटर के बाएँ हाथ की ओर हो। इस कार्यक्षमता का विस्तार करने के लिए, हमें रिवर्स magic method __rmul__ जोड़ना होगा।
# Enabling reverse multiplicationclassNumbers:def__init__(self, a, b):
self.a = a
self.b = b
def__add__(self, other):# Only permit Numbers objects to be addedifnotisinstance(other, Numbers):return NotImplemented
return Numbers(other.a + self.a, other.b + self.b)def__mul__(self, other):ifnotisinstance(other,int):return NotImplemented
return Numbers(self.a * other, self.b * other)def__rmul__(self, other):return self.__mul__(other)def__repr__(self):returnf"{self.__class__.__qualname__}({self.a}, {self.b})"
a = Numbers(2,4)print(5* a)# Should return 10, 20"""
Numbers(10, 20)
"""संचालित द्वारा
अब हम गुणा करने वाली अभिव्यक्ति बना सकते हैं, बिना इस पर विचार किए कि Numbers ऑब्जेक्ट ऑपरेटर के किस तरफ है।
समापन
Python magic methods का लाभ उठाने का मूल सिद्धांत समान रहता है: एक class बनाएँ और object class के magic method को ओवरराइड करें। Python में इतने अधिक magic methods हैं कि अगर हम सभी को अलग-अलग कवर करें तो यह ट्यूटोरियल अत्यधिक लंबा हो जाएगा। हम अत्यधिक अनुशंसा करते हैं कि आप Python प्रलेखन देखें ताकि आपको उन सभी Python magic methods का अंदाज़ा हो सके जिन्हें आप अपनी Python प्रोग्रामिंग स्किल्स को निखारने के लिए उपयोग कर सकते हैं।
Python को एक शक्तिशाली प्रोग्रामिंग भाषा बनाने वाले कारकों में से एक है इसके magic methods। कुछ Pythonista समूहों में, इनके डबल अंडरस्कोर स्वरूप के कारण इन्हें ‘dunder methods’ भी कहा जाता है।
Python में इनका कार्य ‘operator overloading’ नामक प्रक्रिया को निष्पादित करना है, जिसका सीधा अर्थ है किसी पूर्वपरिभाषित ऑपरेटर को विस्तारित अर्थ देना। दूसरे शब्दों में, ऑपरेटर ओवरलोडिंग का उपयोग हमारी कक्षाओं (classes) में कस्टम व्यवहार जोड़ने के लिए किया जाता है ताकि वे Python के ऑपरेटरों और इन-बिल्ट कार्यक्षमताओं के साथ उपयोग योग्य बनें।
इस लेख में, हम Python magic methods को गहराई से समझेंगे, जिसके तहत हम:
इस ट्यूटोरियल में प्रयुक्त कोड को फॉलो करने के लिए यह DataLab वर्कबुक देखें।
Python Methods बनाम Functions
यह समझने से पहले कि magic methods क्या हैं, हमें Python में मेथड और फंक्शन के बीच का अंतर जानना होगा।
Python किसी ऑब्जेक्ट के व्यवहार का निरूपण करने के लिए methods का उपयोग करता है। इस प्रकार, methods किसी ऑब्जेक्ट से संबद्ध होते हैं और उस ऑब्जेक्ट के भीतर मौजूद डेटा पर कुछ ऑपरेशन करते हैं। किसी method की एक और महत्वपूर्ण पहचान self पैरामीटर है, जो हमेशा method को पास किए जाने वाला पहला पैरामीटर होता है।
ध्यान दें: पहले पैरामीटर के रूप में शब्द self होना अनिवार्य नहीं है, लेकिन Pythonistas ने सार्वभौमिक रूप से इसे सर्वोत्तम प्रथा माना है।
Methods उस class पर निर्भर होते हैं जिनसे वे संबद्ध हैं। इसलिए, किसी method को कॉल करने के लिए, डॉट ऑपरेटर से method तक पहुँचने से पहले class का एक instance बनाना आवश्यक है।
दूसरी ओर, एक function अलग होता है: हमें class का instance बनाने की आवश्यकता नहीं होती।
Python functions कोड के ब्लॉक के रूप में परिभाषित चरण होते हैं, जो केवल कॉल किए जाने पर निष्पादित होते हैं। वे किसी भी class ऑब्जेक्ट से स्वतंत्र रूप से परिभाषित होते हैं, यानी उन्हें सीधे उनके नाम से कॉल किया जा सकता है। चूँकि वे किसी class से संबद्ध नहीं हैं, हमें self पैरामीटर पास करने की ज़रूरत नहीं होती – पैरामीटर्स वैकल्पिक होते हैं।
मूल रूप से, एक function बस सुव्यवस्थित निर्देशों का समूह होता है जिसका उपयोग इंटरप्रेटर किसी कार्य को करने के लिए करता है।
हमारे How to call and write functions लेख में विस्तार से बताया गया है कि functions दो प्रकार के होते हैं: बिल्ट-इन और यूज़र-परिभाषित।
कई मायनों में, methods और functions समान हैं - यानी दोनों def स्टेटमेंट से परिभाषित होते हैं। मुख्य अंतर यह है कि methods किसी ऑब्जेक्ट से संबद्ध होते हैं और class के भीतर निहित डेटा पर काम करने के लिए उपयोग किए जाते हैं, जबकि functions स्वतंत्र रूप से परिभाषित होते हैं और प्रोग्राम में कहीं भी नाम से कॉल किए जा सकते हैं।
Python magic methods क्या हैं?
ट्यूटोरियल की शुरुआत में, हमने बताया था कि डबल अंडरस्कोर स्वरूप के कारण magic methods को dunder methods भी कहा जाता है। हमारा अभिप्राय यह था कि सभी Python magic methods दो अंडरस्कोर से शुरू होते और समाप्त होते हैं।
सबसे प्रसिद्ध magic method __init__ है, जो किसी class को विशिष्ट गुणों (attributes) के साथ इनिशियलाइज़ करने में सक्षम बनाता है।
इस class का instance बनाने के लिए, हमें instance के name, age, और role गुणों को निर्दिष्ट करना होगा। उदाहरण के लिए:
ऐसा न करने पर TypeError उत्पन्न होगी।
__init__ method इनिशियलाइज़ेशन और कंस्ट्रक्शन magic methods की श्रेणी में आता है, पर यह अकेला नहीं है। नीचे दी गई तालिका में कुछ अन्य इनिशियलाइज़ेशन और कंस्ट्रक्शन magic methods दिए गए हैं।
__new__(cls, other)
किसी class का नया instance बनाने के लिए उपयोग किया जाता है
__init__(self, other)
नया instance बनने के बाद कॉल होता है; class कंस्ट्रक्टर अभिव्यक्ति को पास किए गए सभी गुण attributes के रूप में उपयोग किए जाएँगे।
__del__(self)
डिस्ट्रक्टर के रूप में भी जाना जाता है; instance के नष्ट किए जाने पर कॉल होता है।
Magic methods को समझने का सबसे सरल तरीका यह मानना हो सकता है कि ये आपके इम्प्लीमेंटेशन और Python इंटरप्रेटर के बीच एक अनुबंध हैं। इस अनुबंध की एक शर्त यह है कि कुछ परिस्थितियों में Python पर्दे के पीछे कुछ क्रियाएँ करेगा, जैसे किसी class instance को विशिष्ट ऑब्जेक्ट्स के साथ इनिशियलाइज़ करना।
दूसरे शब्दों में, किसी magic method को सीधे कॉल करना आपकी ज़िम्मेदारी नहीं है - Python इसे पर्दे के पीछे अपने आप निष्पादित करता है।
स्ट्रिंग रिप्रेज़ेंटेशन methods
Python एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) भाषा है – Python में हर चीज़ एक ऑब्जेक्ट है। जब एक नया ऑब्जेक्ट बनाया जाता है, तो हम अप्रत्यक्ष रूप से एक सम्बद्ध ऑब्जेक्ट भी बनाते हैं क्योंकि सभी classes object से इनहेरिट करती हैं।
टिप्पणी: आप अपने class को परिभाषित करते समय class object पास करके इनहेरिटेंस को स्पष्ट भी कर सकते हैं।
ऊपर दिए गए कोड में, हमने दो खाली classes बनाई हैं, फिर भी जब हमने print स्टेटमेंट चलाया, तो Python इंटरप्रेटर को पता था कि क्या प्रिंट करना है। यह संभव है क्योंकि सभी classes object class (Python में सभी classes की पैरेंट) से इनहेरिट करती हैं, और उसमें __repr__ नामक एक magic method होता है, जिसे print स्टेटमेंट वैल्यू लौटाने के लिए कॉल करता है।
जो पाठक इनहेरिटेंस से परिचित हैं, वे जानते होंगे कि एक चाइल्ड class अपने पैरेंट class के method को उसी नाम का अपना method परिभाषित करके ओवरराइड कर सकता है।
आप __str__ magic method का भी उपयोग कर सकते हैं ताकि print स्टेटमेंट के साथ कॉल होने वाली स्ट्रिंग रिप्रेज़ेंटेशन बनाई जा सके।
वास्तव में, __repr__ magic method, __str__ magic method के बैकअप व्यवहार के रूप में कार्य करता है। इसलिए, जब हम print स्टेटमेंट कॉल करते हैं, तो Python पहले आपकी class में परिभाषित __str__ method को ढूँढता है और उसके न मिलने पर __repr__ method पर वापस जाता है।
नीचे दी गई तालिका में अन्य स्ट्रिंग रिप्रेज़ेंटेशन magic methods की सूची दी गई है।
__str__(self)
Python के इन-बिल्ट str() फंक्शन और print स्टेटमेंट द्वारा किसी ऑब्जेक्ट की अनौपचारिक स्ट्रिंग रिप्रेज़ेंटेशन दिखाने के लिए कॉल किया जाता है। ध्यान दें कि इसके लिए वैध Python अभिव्यक्ति होना आवश्यक नहीं है।
__repr__(self)
Python के इन-बिल्ट repr() फंक्शन और स्ट्रिंग कन्वर्ज़न द्वारा किसी ऑब्जेक्ट की आधिकारिक स्ट्रिंग रिप्रेज़ेंटेशन दिखाने के लिए कॉल किया जाता है। ध्यान दें कि यह एक वैध Python अभिव्यक्ति जैसा दिखना चाहिए, लेकिन यदि यह संभव न हो तो उपयोगी विवरण वाली स्ट्रिंग को प्राथमिकता दी जाती है।
__unicode__(self)
Python के इन-बिल्ट unicode() फंक्शन को इम्प्लीमेंट करने के लिए कॉल किया जाता है और यह एक Unicode ऑब्जेक्ट लौटाता है।
__hash__(self)
Python के इन-बिल्ट hash() फंक्शन और hashed कलेक्शनों के सदस्यों पर किए जाने वाले ऑपरेशंस द्वारा कॉल किया जाता है। यह method एक पूर्णांक लौटाना चाहिए।
__nonzero__(self)
Python के इन-बिल्ट bool() ऑपरेशन द्वारा सत्यता जाँच (truth value testing) को लागू करने के लिए कॉल किया जाता है। यह method True या False (या उनके पूर्णांक समतुल्य 1 या 0) लौटाना चाहिए।
एन्कैप्सुलेशन के “magic” methods
एन्कैप्सुलेशन ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) की मूलभूत अवधारणाओं में से एक है। यह डेटा और उस डेटा पर काम करने वाले methods को एक साथ बाँधने या किसी ऑब्जेक्ट के भीतर कुछ कॉम्पोनेन्ट्स तक सीधे एक्सेस को प्रतिबंधित करने को संदर्भित करता है।
अन्य OOP भाषाओं से आने वाले डेवलपर्स अक्सर यह तर्क देते हैं कि Python कक्षाओं के लिए एन्कैप्सुलेशन को सच में अपनाने में असफल रहा है। ये लोग methods या फ़ील्ड्स के लिए स्पष्ट मॉडिफ़ायर्स के आदी होते हैं जो उन्हें पब्लिक गेटर्स और सेटर्स के साथ प्राइवेट एट्रिब्यूट्स जैसी चीज़ें परिभाषित करने में सक्षम बनाते हैं। Python में अंतर यह है कि एन्कैप्सुलेशन का बहुत सा भाग magic methods के माध्यम से होता है।
उदाहरण के लिए, __setattr__ एक एन्कैप्सुलेशन समाधान है जो हमें किसी एट्रिब्यूट को असाइन करते समय (चाहे वह मौजूद हो या नहीं) व्यवहार परिभाषित करने में सक्षम बनाता है। दूसरे शब्दों में, एट्रिब्यूट्स के मानों में बदलाव के लिए नियम परिभाषित किए जा सकते हैं।
ऊपर दिए गए कोड में, हमने Alphabet नामक एक class बनाई जिसके कोई एट्रिब्यूट्स नहीं हैं, लेकिन हमने Python को यह बताया कि class instance के किसी भी एट्रिब्यूट को सेट करते समय उसे कैपिटल में बदलना है।
हम समझते हैं कि कुछ पाठकों के लिए OOP थोड़ी दूर की चीज़ हो सकती है। Python में OOP पर पकड़ मज़बूत करने के लिए DataCamp का Python Programmer Track देखें।
Math magic methods
Python magic methods की एक और श्रेणी गणितीय magic methods हैं (जिन्हें सामान्य arithmetic ऑपरेटर्स भी कहा जाता है)। Python में अभिव्यक्तियाँ विशेष प्रतीकों, यानी ‘ऑपरेटर्स’ का उपयोग करके बनाई जाती हैं। किसी अभिव्यक्ति में ऐसे ऑपरेटर्स का उपयोग करने का अर्थ उन ऑब्जेक्ट्स का निर्माण करना है जिनमें संबंधित math magic methods हों। ऐसा न करने पर TypeError उत्पन्न होगी।
ऊपर दिए गए कोड में, हमने Numbers class के कई instances बनाने और उन्हें आपस में जोड़ने का प्रयास किया, जिससे अपेक्षित रूप से त्रुटि आई। इस त्रुटि का एक समाधान यह हो सकता है कि हम अपनी class में नंबर जोड़ने के लिए कोई method बनाएँ, लेकिन इससे हम अभिव्यक्तियाँ (expressions) बनाने से वंचित रहेंगे।
एक बेहतर समाधान __add__ magic method को निम्नानुसार इम्प्लीमेंट करना होगा:
ऊपर दिए गए कोड उदाहरण में हम केवल दो Numbers ऑब्जेक्ट्स को आपस में जोड़ सकते हैं। आइए एक और math magic method इम्प्लीमेंट करें जो हमें किसी Numbers ऑब्जेक्ट को एक पूर्णांक से गुणा करने की अनुमति दे।
ऊपर दिए गए कोड में, हमने __mul__ magic method जोड़ा ताकि हम अपनी कस्टम class के नंबरों को किसी पूर्णांक से गुणा कर सकें।
ध्यान दें कि Numbers ऑब्जेक्ट * ऑपरेटर के बाएँ तरफ है - यह संयोग नहीं है। आइए इसे ऑपरेटर के दाएँ तरफ रखें और देखें क्या होता है।
Python एक TypeError फेंकता है।
हमारे द्वारा इम्प्लीमेंट किया गया __mul__ magic method केवल तब काम करता है जब Numbers ऑब्जेक्ट * ऑपरेटर के बाएँ हाथ की ओर हो। इस कार्यक्षमता का विस्तार करने के लिए, हमें रिवर्स magic method __rmul__ जोड़ना होगा।
अब हम गुणा करने वाली अभिव्यक्ति बना सकते हैं, बिना इस पर विचार किए कि Numbers ऑब्जेक्ट ऑपरेटर के किस तरफ है।
समापन
Python magic methods का लाभ उठाने का मूल सिद्धांत समान रहता है: एक class बनाएँ और object class के magic method को ओवरराइड करें। Python में इतने अधिक magic methods हैं कि अगर हम सभी को अलग-अलग कवर करें तो यह ट्यूटोरियल अत्यधिक लंबा हो जाएगा। हम अत्यधिक अनुशंसा करते हैं कि आप Python प्रलेखन देखें ताकि आपको उन सभी Python magic methods का अंदाज़ा हो सके जिन्हें आप अपनी Python प्रोग्रामिंग स्किल्स को निखारने के लिए उपयोग कर सकते हैं।