पायथन - ऑब्जेक्ट ओरिएंटेड

पायथन अस्तित्व में आने के बाद से एक वस्तु-उन्मुख भाषा रही है। इस वजह से, कक्षाएं और ऑब्जेक्ट बनाना और उपयोग करना बिल्कुल आसान है। यह अध्याय आपको पायथन के ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग समर्थन का उपयोग करने में एक विशेषज्ञ बनने में मदद करता है।

यदि आपके पास ऑब्जेक्ट-ओरिएंटेड (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/python

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.age = 7  # Add an 'age' attribute.
emp1.age = 8  # Modify 'age' attribute.
del emp1.age  # Delete 'age' attribute.

विशेषताओं तक पहुंचने के लिए सामान्य विवरणों का उपयोग करने के बजाय, आप निम्नलिखित कार्यों का उपयोग कर सकते हैं -

  • getattr(obj, name[, default]) - वस्तु की विशेषता तक पहुँचने के लिए।

  • hasattr(obj,name) - यह देखने के लिए कि कोई विशेषता मौजूद है या नहीं।

  • setattr(obj,name,value)- एक विशेषता सेट करने के लिए। यदि विशेषता मौजूद नहीं है, तो इसे बनाया जाएगा।

  • delattr(obj, name) - एक विशेषता को हटाने के लिए।

hasattr(emp1, 'age')    # Returns true if 'age' attribute exists
getattr(emp1, 'age')    # Returns value of 'age' attribute
setattr(emp1, 'age', 8) # Set attribute 'age' at 8
delattr(empl, 'age')    # Delete attribute 'age'

बिल्ट-इन कक्षा विशेषताएँ

प्रत्येक पायथन वर्ग अंतर्निहित विशेषताओं का पालन करता है और उन्हें किसी अन्य विशेषता की तरह डॉट ऑपरेटर का उपयोग करके एक्सेस किया जा सकता है -

  • __dict__ - शब्दकोश वर्ग के नाम स्थान युक्त।

  • __doc__ - वर्ग प्रलेखन स्ट्रिंग या कोई नहीं, यदि अपरिभाषित है।

  • __name__ - कक्षा का नाम।

  • __module__- मॉड्यूल नाम जिसमें कक्षा को परिभाषित किया गया है। यह विशेषता इंटरैक्टिव मोड में "__main__" है।

  • __bases__ - बेस क्लास लिस्ट में उनके होने के क्रम में बेस क्लास युक्त संभवतः एक खाली टपल।

उपरोक्त वर्ग के लिए आइए हम इन सभी विशेषताओं तक पहुँचने का प्रयास करें -

#!/usr/bin/python

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

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__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount':
<function displayCount at 0xb7c84994>, 'empCount': 2, 
'displayEmployee': <function displayEmployee at 0xb7c8441c>, 
'__doc__': 'Common base class for all employees', 
'__init__': <function __init__ at 0xb7c846bc>}

वस्तुओं को नष्ट करना (कचरा संग्रहण)

पाइथन मेमोरी स्पेस को खाली करने के लिए अनावश्यक रूप से ऑब्जेक्ट्स (अंतर्निहित प्रकार या वर्ग उदाहरण) को हटाता है। जिस प्रक्रिया से पायथन समय-समय पर स्मृति के ब्लॉक को याद करता है कि अब उपयोग में नहीं हैं, कचरा संग्रह कहा जाता है।

पायथन का कचरा कलेक्टर कार्यक्रम निष्पादन के दौरान चलता है और किसी वस्तु की संदर्भ गणना शून्य तक पहुंचने पर चालू हो जाता है। एक ऑब्जेक्ट का संदर्भ गिनती में परिवर्तन करने वाले उपनामों की संख्या के रूप में बदलता है।

किसी ऑब्जेक्ट का संदर्भ काउंट तब बढ़ जाता है जब उसे एक नया नाम सौंपा जाता है या कंटेनर (सूची, टपल, या शब्दकोश) में रखा जाता है। ऑब्जेक्ट की रेफरेंस काउंट तब कम हो जाती है जब उसे डेल के साथ डिलीट कर दिया जाता है , उसका रेफरेंस रिजेक्ट हो जाता है या उसका रेफरेंस स्कोप से बाहर हो जाता है। जब किसी ऑब्जेक्ट की संदर्भ संख्या शून्य तक पहुंच जाती है, तो पायथन अपने आप इसे इकट्ठा करता है।

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/python

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

जब उपरोक्त कोड निष्पादित किया जाता है, तो यह निम्नलिखित परिणाम उत्पन्न करता है -

3083401324 3083401324 3083401324
Point destroyed

Note- आदर्श रूप से, आपको अपनी कक्षाओं को अलग फ़ाइल में परिभाषित करना चाहिए, फिर आपको आयात विवरण का उपयोग करके उन्हें अपने मुख्य प्रोग्राम फ़ाइल में आयात करना चाहिए ।

कक्षा में प्रवेश

स्क्रैच से शुरू करने के बजाय, आप नए वर्ग के नाम के बाद मूल वर्ग में कोष्ठक में सूचीबद्ध करके इसे एक पूर्ववर्ती कक्षा से प्राप्त करके एक वर्ग बना सकते हैं।

बाल वर्ग अपने मूल वर्ग की विशेषताओं को विरासत में देता है, और आप उन विशेषताओं का उपयोग कर सकते हैं जैसे कि उन्हें बाल वर्ग में परिभाषित किया गया था। एक बच्चा वर्ग माता-पिता से डेटा सदस्यों और विधियों को भी ओवरराइड कर सकता है।

वाक्य - विन्यास

व्युत्पन्न वर्गों को उनके मूल वर्ग की तरह घोषित किया जाता है; हालांकि, वर्ग के नाम के बाद से आधार वर्ग की एक सूची दी गई है -

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

उदाहरण

#!/usr/bin/python

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 class B
.....

class C(A, B):   # subclass of A and B
.....

आप दो वर्गों और उदाहरणों के रिश्तों की जांच के लिए issubclass () या आइंस्टीन () फ़ंक्शंस का उपयोग कर सकते हैं।

  • issubclass(sub, sup) अगर बचे हुए उपवर्ग में बूलियन फ़ंक्शन सही है sub वास्तव में सुपरक्लास का एक उपवर्ग है sup

  • isinstance(obj, Class)बूलियन फंक्शन सही साबित होता है यदि ओब्ज क्लास क्लास का एक उदाहरण है या क्लास के एक उपवर्ग का एक उदाहरण है

ओवरराइडिंग के तरीके

आप हमेशा अपने पैरेंट क्लास के तरीकों को ओवरराइड कर सकते हैं। माता-पिता के तरीकों को ओवरराइड करने का एक कारण यह है कि आप अपने उपवर्ग में विशेष या अलग कार्यक्षमता चाहते हैं।

उदाहरण

#!/usr/bin/python

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/python

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/python

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