पायथन 3 - ऑब्जेक्ट ओरिएंटेड
जब से अस्तित्व में आया तब से पायथन एक वस्तु-उन्मुख भाषा रही है। इसके कारण, कक्षाओं और वस्तुओं का निर्माण और उपयोग करना बिलकुल आसान है। यह अध्याय आपको पायथन के ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग समर्थन का उपयोग करने में एक विशेषज्ञ बनने में मदद करता है।
यदि आपके पास ऑब्जेक्ट-ओरिएंटेड (OO) प्रोग्रामिंग के साथ कोई पिछला अनुभव नहीं है, तो आप इस पर एक परिचयात्मक पाठ्यक्रम या कम से कम कुछ प्रकार के एक ट्यूटोरियल से परामर्श करना चाह सकते हैं ताकि आपके पास मूल अवधारणाओं की समझ हो।
हालाँकि, यहाँ आपकी सहायता के लिए ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) का एक छोटा सा परिचय है -
ओओपी शब्दावली का अवलोकन
Class- किसी ऑब्जेक्ट के लिए एक उपयोगकर्ता-परिभाषित प्रोटोटाइप जो विशेषताओं के एक सेट को परिभाषित करता है जो वर्ग के किसी भी ऑब्जेक्ट को चिह्नित करता है। विशेषताएँ डेटा सदस्य (वर्ग चर और उदाहरण चर) और विधियाँ हैं, जिन्हें डॉट नोटेशन के माध्यम से एक्सेस किया जाता है।
Class variable- एक चर जो किसी वर्ग के सभी उदाहरणों द्वारा साझा किया जाता है। वर्ग चर को एक वर्ग के भीतर परिभाषित किया जाता है लेकिन कक्षा के किसी भी तरीके के बाहर। वर्ग चर का उपयोग नहीं किया जाता है, उदाहरण के रूप में अक्सर चर का उपयोग किया जाता है।
Data member - एक वर्ग चर या उदाहरण चर जो एक वर्ग और उसकी वस्तुओं से जुड़ा डेटा रखता है।
Function overloading- एक विशेष कार्य के लिए एक से अधिक व्यवहार का कार्य। प्रदर्शन किया गया ऑपरेशन शामिल वस्तुओं या तर्कों के प्रकारों से भिन्न होता है।
Instance variable - एक चर जो एक विधि के अंदर परिभाषित किया गया है और केवल एक वर्ग की वर्तमान आवृत्ति से संबंधित है।
Inheritance - एक वर्ग की विशेषताओं को अन्य वर्गों से स्थानांतरित करना जो इससे प्राप्त होते हैं।
Instance- एक निश्चित वर्ग की एक व्यक्तिगत वस्तु। एक ऑब्जेक्ट ओब्ज, जो एक वर्ग सर्कल से संबंधित है, उदाहरण के लिए, वर्ग सर्कल का एक उदाहरण है।
Instantiation - एक वर्ग के उदाहरण का निर्माण।
Method - एक विशेष प्रकार का फ़ंक्शन जिसे एक वर्ग परिभाषा में परिभाषित किया गया है।
Object- एक डेटा संरचना का एक अनूठा उदाहरण जो इसकी कक्षा द्वारा परिभाषित किया गया है। ऑब्जेक्ट में डेटा सदस्य (वर्ग चर और उदाहरण चर) और विधियाँ दोनों शामिल हैं।
Operator overloading - एक विशेष ऑपरेटर को एक से अधिक फ़ंक्शन का असाइनमेंट।
कक्षाएं बनाना
वर्ग बयान एक नया वर्ग परिभाषा पैदा करता है। क्लास का नाम तुरंत कीवर्ड क्लास का अनुसरण करता है और उसके बाद कोलन निम्नानुसार है -
class ClassName:
'Optional class documentation string'
class_suite
क्लास में डॉक्यूमेंटेशन स्ट्रिंग होती है, जिसके जरिए एक्सेस किया जा सकता है ClassName.__doc__।
class_suite वर्ग के सदस्यों, डेटा विशेषताओं और कार्यों को परिभाषित करने वाले सभी घटक विवरण शामिल हैं।
उदाहरण
निम्नलिखित एक साधारण अजगर वर्ग का एक उदाहरण है -
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
वैरिएबल एंपकाउंट एक क्लास वैरिएबल है, जिसका वैल्यू इस क्लास के सभी इंस्टेंस के बीच शेयर किया जाता है। इसे क्लास के अंदर या कक्षा के बाहर से Employee.empCount के रूप में एक्सेस किया जा सकता है ।
पहली विधि __init __ () एक विशेष विधि है, जिसे क्लास कंस्ट्रक्टर या इनिशियलाइज़ेशन विधि कहा जाता है जिसे आप इस वर्ग का एक नया उदाहरण बनाते समय पायथन कॉल करते हैं।
आप अन्य कक्षा विधियों को सामान्य कार्यों की तरह इस अपवाद के साथ घोषित करते हैं कि प्रत्येक विधि का पहला तर्क स्वयं है । पायथन आपके लिए सूची में स्व तर्क जोड़ता है ; विधियों को कॉल करने पर आपको इसे शामिल करने की आवश्यकता नहीं है।
इंस्टेंस ऑब्जेक्ट बनाना
एक कक्षा के उदाहरण बनाने के लिए, आप कक्षा को कक्षा के नाम का उपयोग करके कॉल करते हैं और जो भी तर्क देते हैं, वह __in__ विधि को स्वीकार करता है।
This would create first object of Employee class
emp1 = Employee("Zara", 2000)
This would create second object of Employee class
emp2 = Employee("Manni", 5000)
एक्सेस करने के गुण
आप ऑब्जेक्ट ऑपरेटर के ऑब्जेक्ट के साथ डॉट ऑपरेटर का उपयोग करके एक्सेस करते हैं। वर्ग नाम का उपयोग वर्ग नाम के रूप में किया जाएगा।
emp1.displayEmployee()
emp2.displayEmployee()
print ("Total Employee %d" % Employee.empCount)
अब, सभी अवधारणाओं को एक साथ रखना -
#!/usr/bin/python3
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
#This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
#This would create second object of Employee class"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print ("Total Employee %d" % Employee.empCount)
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Name : Zara ,Salary: 2000
Name : Manni ,Salary: 5000
Total Employee 2
आप किसी भी समय कक्षाओं और वस्तुओं की विशेषताओं को जोड़, हटा या संशोधित कर सकते हैं -
emp1.salary = 7000 # Add an 'salary' attribute.
emp1.name = 'xyz' # Modify 'age' attribute.
del emp1.salary # Delete 'age' attribute.
विशेषताओं तक पहुंचने के लिए सामान्य विवरणों का उपयोग करने के बजाय, आप निम्नलिखित कार्यों का उपयोग कर सकते हैं -
getattr(obj, name[, default]) - वस्तु की विशेषता तक पहुँचने के लिए।
hasattr(obj,name) - यह देखने के लिए कि कोई विशेषता मौजूद है या नहीं।
setattr(obj,name,value)- एक विशेषता सेट करने के लिए। यदि विशेषता मौजूद नहीं है, तो इसे बनाया जाएगा।
delattr(obj, name) - एक विशेषता को हटाने के लिए।
hasattr(emp1, 'salary') # Returns true if 'salary' attribute exists
getattr(emp1, 'salary') # Returns value of 'salary' attribute
setattr(emp1, 'salary', 7000) # Set attribute 'salary' at 7000
delattr(emp1, 'salary') # Delete attribute 'salary'
बिल्ट-इन कक्षा विशेषताएँ
प्रत्येक पायथन वर्ग अंतर्निहित विशेषताओं का पालन करता है और उन्हें किसी अन्य विशेषता की तरह डॉट ऑपरेटर का उपयोग करके एक्सेस किया जा सकता है -
__dict__ - शब्दकोश वर्ग के नाम स्थान युक्त।
__doc__ - वर्ग प्रलेखन स्ट्रिंग या कोई नहीं, यदि अपरिभाषित है।
__name__ - कक्षा का नाम।
__module__- मॉड्यूल नाम जिसमें कक्षा को परिभाषित किया गया है। यह विशेषता इंटरैक्टिव मोड में "__main__" है।
__bases__ - बेस क्लास लिस्ट में उनके होने के क्रम में बेस क्लास युक्त संभवतः एक खाली टपल।
उपरोक्त वर्ग के लिए आइए हम इन सभी विशेषताओं तक पहुँचने का प्रयास करें -
#!/usr/bin/python3
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
emp1 = Employee("Zara", 2000)
emp2 = Employee("Manni", 5000)
print ("Employee.__doc__:", Employee.__doc__)
print ("Employee.__name__:", Employee.__name__)
print ("Employee.__module__:", Employee.__module__)
print ("Employee.__bases__:", Employee.__bases__)
print ("Employee.__dict__:", Employee.__dict__ )
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {
'displayCount': <function Employee.displayCount at 0x0160D2B8>,
'__module__': '__main__', '__doc__': 'Common base class for all employees',
'empCount': 2, '__init__':
<function Employee.__init__ at 0x0124F810>, 'displayEmployee':
<function Employee.displayEmployee at 0x0160D300>,
'__weakref__':
<attribute '__weakref__' of 'Employee' objects>, '__dict__':
<attribute '__dict__' of 'Employee' objects>
}
वस्तुओं को नष्ट करना (कचरा संग्रहण)
पाइथन मेमोरी स्पेस को खाली करने के लिए अनावश्यक रूप से ऑब्जेक्ट्स (अंतर्निहित प्रकार या वर्ग उदाहरण) को हटाता है। जिस प्रक्रिया से पायथन समय-समय पर स्मृति के ब्लॉक को याद करता है कि अब उपयोग में नहीं हैं, को कचरा संग्रह कहा जाता है।
पायथन का कचरा कलेक्टर कार्यक्रम निष्पादन के दौरान चलता है और किसी वस्तु की संदर्भ गणना शून्य तक पहुंचने पर चालू हो जाता है। एक ऑब्जेक्ट का संदर्भ गिनती में परिवर्तन करने वाले उपनामों की संख्या के रूप में बदलता है।
किसी ऑब्जेक्ट का संदर्भ काउंट तब बढ़ जाता है जब उसे एक नया नाम सौंपा जाता है या कंटेनर (सूची, टपल, या शब्दकोश) में रखा जाता है। ऑब्जेक्ट की रेफरेंस काउंट तब कम हो जाती है जब उसे डेल के साथ डिलीट कर दिया जाता है , उसका रेफरेंस रिजेक्ट हो जाता है या उसका रेफरेंस स्कोप से बाहर चला जाता है। जब किसी ऑब्जेक्ट की संदर्भ संख्या शून्य तक पहुंच जाती है, तो पायथन अपने आप इसे इकट्ठा करता है।
a = 40 # Create object <40>
b = a # Increase ref. count of <40>
c = [b] # Increase ref. count of <40>
del a # Decrease ref. count of <40>
b = 100 # Decrease ref. count of <40>
c[0] = -1 # Decrease ref. count of <40>
जब कचरा कलेक्टर अनाथ उदाहरण को नष्ट कर देता है और अपने स्थान को पुनः प्राप्त करता है, तो आप सामान्य रूप से नोटिस नहीं करेंगे। हालांकि, एक वर्ग विशेष विधि को लागू कर सकता है __del __ () , जिसे एक विध्वंसक कहा जाता है, जिसे तब लागू किया जाता है जब उदाहरण नष्ट होने वाला हो। इस पद्धति का उपयोग किसी भी गैर-स्मृति संसाधन को उदाहरण के लिए साफ़ करने के लिए किया जा सकता है।
उदाहरण
यह __del __ () विध्वंसक एक उदाहरण के वर्ग नाम को प्रिंट करता है जो नष्ट होने वाला है -
#!/usr/bin/python3
class Point:
def __init__( self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print (class_name, "destroyed")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print (id(pt1), id(pt2), id(pt3)) # prints the ids of the obejcts
del pt1
del pt2
del pt3
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
140338326963984 140338326963984 140338326963984
Point destroyed
Note- आदर्श रूप से, आपको अपनी कक्षाओं को एक अलग फ़ाइल में परिभाषित करना चाहिए, फिर आपको आयात विवरण का उपयोग करके उन्हें अपने मुख्य प्रोग्राम फ़ाइल में आयात करना चाहिए ।
उपर्युक्त उदाहरण में, पॉइंट क्लास की परिभाषा को पॉइंटहोम में समाहित किया गया है और इसमें कोई अन्य निष्पादन योग्य कोड नहीं है।
#!/usr/bin/python3
import point
p1 = point.Point()
कक्षा में प्रवेश
एक खरोंच से शुरू करने के बजाय, आप नए वर्ग के नाम के बाद मूल वर्ग में कोष्ठक में सूचीबद्ध करके इसे पहले से मौजूद वर्ग से प्राप्त करके एक वर्ग बना सकते हैं।
बाल वर्ग अपने मूल वर्ग की विशेषताओं को विरासत में देता है, और आप उन विशेषताओं का उपयोग कर सकते हैं जैसे कि उन्हें बाल वर्ग में परिभाषित किया गया था। एक बच्चा वर्ग माता-पिता से डेटा सदस्यों और विधियों को भी ओवरराइड कर सकता है।
वाक्य - विन्यास
व्युत्पन्न वर्गों को उनके मूल वर्ग की तरह घोषित किया जाता है; हालांकि, वर्ग के नाम के बाद से आधार वर्ग की एक सूची दी गई है -
class SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
उदाहरण
#!/usr/bin/python3
class Parent: # define parent class
parentAttr = 100
def __init__(self):
print ("Calling parent constructor")
def parentMethod(self):
print ('Calling parent method')
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print ("Parent attribute :", Parent.parentAttr)
class Child(Parent): # define child class
def __init__(self):
print ("Calling child constructor")
def childMethod(self):
print ('Calling child method')
c = Child() # instance of child
c.childMethod() # child calls its method
c.parentMethod() # calls parent's method
c.setAttr(200) # again call parent's method
c.getAttr() # again call parent's method
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200
इसी तरह से, आप कई मूल वर्गों से निम्नानुसार एक कक्षा चला सकते हैं -
class A: # define your class A
.....
class B: # define your calss B
.....
class C(A, B): # subclass of A and B
.....
आप दो वर्गों और उदाहरणों के रिश्तों की जांच के लिए issubclass () या आइंस्टीन () फ़ंक्शंस का उपयोग कर सकते हैं।
issubclass(sub, sup) बूलियन फ़ंक्शन सही है, यदि दिए गए उपवर्ग sub वास्तव में सुपरक्लास का एक उपवर्ग है sup।
isinstance(obj, Class)बूलियन फ़ंक्शन सही है, अगर obj क्लास क्लास का एक उदाहरण है या क्लास के एक उपवर्ग का एक उदाहरण है
ओवरराइडिंग के तरीके
आप हमेशा अपने पैरेंट क्लास के तरीकों को ओवरराइड कर सकते हैं। माता-पिता के तरीकों को ओवरराइड करने का एक कारण यह है कि आप अपने उपवर्ग में विशेष या अलग कार्यक्षमता चाहते हैं।
उदाहरण
#!/usr/bin/python3
class Parent: # define parent class
def myMethod(self):
print ('Calling parent method')
class Child(Parent): # define child class
def myMethod(self):
print ('Calling child method')
c = Child() # instance of child
c.myMethod() # child calls overridden method
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Calling child method
बेस ओवरलोडिंग के तरीके
निम्न तालिका कुछ सामान्य कार्यक्षमता को सूचीबद्ध करती है जिसे आप अपनी कक्षाओं में ओवरराइड कर सकते हैं -
अनु क्रमांक। | विधि, विवरण और नमूना कॉल |
---|---|
1 | __init__ ( self [,args...] ) कंस्ट्रक्टर (किसी भी वैकल्पिक तर्क के साथ) नमूना कॉल: obj = className (args) |
2 | __del__( self ) विध्वंसक, किसी वस्तु को हटा देता है नमूना कॉल: डेल obj |
3 | __repr__( self ) अमूल्य स्ट्रिंग प्रतिनिधित्व नमूना कॉल: repr (obj) |
4 | __str__( self ) मुद्रण योग्य स्ट्रिंग प्रतिनिधित्व नमूना कॉल: str (obj) |
5 | __cmp__ ( self, x ) वस्तु तुलना नमूना कॉल: cmp (obj, x) |
ओवरलोडिंग संचालक
मान लीजिए कि आपने द्वि-आयामी वैक्टर का प्रतिनिधित्व करने के लिए एक वेक्टर वर्ग बनाया है। जब आप उन्हें जोड़ने के लिए प्लस ऑपरेटर का उपयोग करते हैं तो क्या होता है? सबसे अधिक संभावना है कि पायथन आप पर चिल्लाएगा।
हालाँकि, आप वेक्टर को पूरा करने के लिए अपनी कक्षा में __add__ विधि को परिभाषित कर सकते हैं और फिर प्लस ऑपरेटर अपेक्षा के अनुसार व्यवहार करेगा -
उदाहरण
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Vector(7,8)
डेटा छिपाना
किसी ऑब्जेक्ट की विशेषताएँ वर्ग परिभाषा के बाहर दिखाई दे सकती हैं या नहीं भी। आपको डबल अंडरस्कोर उपसर्ग वाली विशेषताओं को नाम देने की आवश्यकता है, और फिर वे विशेषताएँ बाहरी लोगों को सीधे दिखाई नहीं देंगी।
उदाहरण
#!/usr/bin/python3
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.__secretCount)
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
1
2
Traceback (most recent call last):
File "test.py", line 12, in <module>
print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'
पायथन आंतरिक रूप से वर्ग नाम को शामिल करने के लिए नाम बदलकर उन सदस्यों की रक्षा करता है। आप ऐसी विशेषताओं को ऑब्जेक्ट के रूप में एक्सेस कर सकते हैं । _className__attrName यदि आप निम्नलिखित के रूप में अपनी अंतिम पंक्ति को बदल देंगे, तो यह आपके लिए काम करता है -
.........................
print (counter._JustCounter__secretCount)
जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
1
2
2