Python - Objektorientiert

Python ist seit seiner Existenz eine objektorientierte Sprache. Aus diesem Grund ist das Erstellen und Verwenden von Klassen und Objekten ausgesprochen einfach. Dieses Kapitel hilft Ihnen, ein Experte für die objektorientierte Programmierunterstützung von Python zu werden.

Wenn Sie noch keine Erfahrung mit objektorientierter Programmierung (OO) haben, sollten Sie einen Einführungskurs oder zumindest ein Tutorial konsultieren, um die grundlegenden Konzepte zu verstehen.

Hier ist jedoch eine kleine Einführung in die objektorientierte Programmierung (OOP), um Sie auf den neuesten Stand zu bringen -

Übersicht über die OOP-Terminologie

  • Class- Ein benutzerdefinierter Prototyp für ein Objekt, der eine Reihe von Attributen definiert, die jedes Objekt der Klasse charakterisieren. Die Attribute sind Datenelemente (Klassenvariablen und Instanzvariablen) und Methoden, auf die über die Punktnotation zugegriffen wird.

  • Class variable- Eine Variable, die von allen Instanzen einer Klasse gemeinsam genutzt wird. Klassenvariablen werden innerhalb einer Klasse definiert, jedoch außerhalb einer der Methoden der Klasse. Klassenvariablen werden nicht so häufig verwendet wie Instanzvariablen.

  • Data member - Eine Klassenvariable oder Instanzvariable, die Daten enthält, die einer Klasse und ihren Objekten zugeordnet sind.

  • Function overloading- Die Zuordnung von mehr als einem Verhalten zu einer bestimmten Funktion. Die ausgeführte Operation hängt von den beteiligten Objekttypen oder Argumenten ab.

  • Instance variable - Eine Variable, die innerhalb einer Methode definiert ist und nur zur aktuellen Instanz einer Klasse gehört.

  • Inheritance - Die Übertragung der Merkmale einer Klasse auf andere daraus abgeleitete Klassen.

  • Instance- Ein einzelnes Objekt einer bestimmten Klasse. Ein Objektobjekt, das beispielsweise zu einer Klasse Circle gehört, ist eine Instanz der Klasse Circle.

  • Instantiation - Die Erstellung einer Instanz einer Klasse.

  • Method - Eine spezielle Art von Funktion, die in einer Klassendefinition definiert ist.

  • Object- Eine eindeutige Instanz einer Datenstruktur, die von ihrer Klasse definiert wird. Ein Objekt umfasst sowohl Datenelemente (Klassenvariablen und Instanzvariablen) als auch Methoden.

  • Operator overloading - Die Zuordnung von mehr als einer Funktion zu einem bestimmten Bediener.

Klassen erstellen

Die Klassenanweisung erstellt eine neue Klassendefinition. Der Name der Klasse folgt unmittelbar auf die Schlüsselwortklasse , gefolgt von einem Doppelpunkt wie folgt:

class ClassName:
   'Optional class documentation string'
   class_suite
  • Die Klasse verfügt über eine Dokumentationszeichenfolge, auf die über ClassName .__ doc__ zugegriffen werden kann .

  • Die class_suite besteht aus allen Komponentenanweisungen, die Klassenmitglieder, Datenattribute und Funktionen definieren.

Beispiel

Es folgt das Beispiel einer einfachen Python-Klasse -

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
  • Die Variable empCount ist eine Klassenvariable, deren Wert von allen Instanzen dieser Klasse gemeinsam genutzt wird. Auf diese kann innerhalb oder außerhalb der Klasse als Employee.empCount zugegriffen werden .

  • Die erste Methode __init __ () ist eine spezielle Methode, die als Klassenkonstruktor oder Initialisierungsmethode bezeichnet wird und von Python aufgerufen wird, wenn Sie eine neue Instanz dieser Klasse erstellen.

  • Sie deklarieren andere Klassenmethoden wie normale Funktionen mit der Ausnahme, dass das erste Argument für jede Methode self ist . Python fügt das Selbst Argument für Sie in die Liste; Sie müssen es nicht einschließen, wenn Sie die Methoden aufrufen.

Instanzobjekte erstellen

Um Instanzen einer Klasse zu erstellen, rufen Sie die Klasse mit dem Klassennamen auf und übergeben die Argumente, die die Methode __init__ akzeptiert.

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)

Zugriff auf Attribute

Sie greifen auf die Objektattribute mit dem Punktoperator mit Objekt zu. Auf die Klassenvariable wird wie folgt zugegriffen:

emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

Nun alle Konzepte zusammenfügen -

#!/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

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

Name :  Zara ,Salary:  2000
Name :  Manni ,Salary:  5000
Total Employee 2

Sie können jederzeit Attribute von Klassen und Objekten hinzufügen, entfernen oder ändern.

emp1.age = 7  # Add an 'age' attribute.
emp1.age = 8  # Modify 'age' attribute.
del emp1.age  # Delete 'age' attribute.

Anstatt die normalen Anweisungen für den Zugriff auf Attribute zu verwenden, können Sie die folgenden Funktionen verwenden:

  • Das getattr(obj, name[, default]) - um auf das Attribut des Objekts zuzugreifen.

  • Das hasattr(obj,name) - um zu überprüfen, ob ein Attribut vorhanden ist oder nicht.

  • Das setattr(obj,name,value)- um ein Attribut festzulegen. Wenn das Attribut nicht vorhanden ist, wird es erstellt.

  • Das delattr(obj, name) - um ein Attribut zu löschen.

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'

Integrierte Klassenattribute

Jede Python-Klasse folgt weiterhin den integrierten Attributen und kann wie jedes andere Attribut mit dem Punktoperator aufgerufen werden.

  • __dict__ - Wörterbuch mit dem Namespace der Klasse.

  • __doc__ - Klassendokumentationszeichenfolge oder keine, falls nicht definiert.

  • __name__ - Klassenname.

  • __module__- Modulname, in dem die Klasse definiert ist. Dieses Attribut ist im interaktiven Modus "__main__".

  • __bases__ - Ein möglicherweise leeres Tupel, das die Basisklassen in der Reihenfolge ihres Auftretens in der Basisklassenliste enthält.

Lassen Sie uns für die obige Klasse versuchen, auf alle diese Attribute zuzugreifen -

#!/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__

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

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>}

Objekte zerstören (Garbage Collection)

Python löscht nicht benötigte Objekte (integrierte Typen oder Klasseninstanzen) automatisch, um den Speicherplatz freizugeben. Der Prozess, mit dem Python Speicherblöcke, die nicht mehr verwendet werden, regelmäßig zurückfordert, wird als Garbage Collection bezeichnet.

Der Garbage Collector von Python wird während der Programmausführung ausgeführt und ausgelöst, wenn der Referenzzähler eines Objekts Null erreicht. Die Referenzanzahl eines Objekts ändert sich, wenn sich die Anzahl der Aliase ändert, die darauf verweisen.

Die Referenzanzahl eines Objekts erhöht sich, wenn ihm ein neuer Name zugewiesen oder in einem Container (Liste, Tupel oder Wörterbuch) abgelegt wird. Die Referenzanzahl des Objekts nimmt ab, wenn es mit del gelöscht wird , seine Referenz neu zugewiesen wird oder seine Referenz den Gültigkeitsbereich verlässt. Wenn der Referenzzähler eines Objekts Null erreicht, sammelt Python ihn automatisch.

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>

Normalerweise werden Sie nicht bemerken, wenn der Garbage Collector eine verwaiste Instanz zerstört und ihren Speicherplatz zurückerobert. Eine Klasse kann jedoch die spezielle Methode __del __ () implementieren , die als Destruktor bezeichnet wird und aufgerufen wird, wenn die Instanz zerstört werden soll. Diese Methode kann verwendet werden, um alle von einer Instanz verwendeten Nicht-Speicherressourcen zu bereinigen.

Beispiel

Dieser __del __ () - Destruktor gibt den Klassennamen einer Instanz aus, die zerstört werden soll.

#!/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

Wenn der obige Code ausgeführt wird, erzeugt er folgendes Ergebnis:

3083401324 3083401324 3083401324
Point destroyed

Note- Idealerweise sollten Sie Ihre Klassen in einer separaten Datei definieren und sie dann mithilfe der import- Anweisung in Ihre Hauptprogrammdatei importieren .

Klassenvererbung

Anstatt von vorne zu beginnen, können Sie eine Klasse erstellen, indem Sie sie von einer bereits vorhandenen Klasse ableiten, indem Sie die übergeordnete Klasse in Klammern nach dem neuen Klassennamen auflisten.

Die untergeordnete Klasse erbt die Attribute ihrer übergeordneten Klasse, und Sie können diese Attribute so verwenden, als wären sie in der untergeordneten Klasse definiert. Eine untergeordnete Klasse kann auch Datenelemente und Methoden des übergeordneten Elements überschreiben.

Syntax

Abgeleitete Klassen werden ähnlich wie ihre übergeordnete Klasse deklariert. Nach dem Klassennamen wird jedoch eine Liste der Basisklassen angezeigt, von denen geerbt werden soll.

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

Beispiel

#!/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

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

Auf ähnliche Weise können Sie eine Klasse aus mehreren übergeordneten Klassen wie folgt steuern:

class A:        # define your class A
.....

class B:         # define your class B
.....

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

Mit den Funktionen issubclass () oder isinstance () können Sie die Beziehungen zweier Klassen und Instanzen überprüfen.

  • Das issubclass(sub, sup) Die boolesche Funktion gibt true zurück, wenn die angegebene Unterklasse sub ist in der Tat eine Unterklasse der Oberklasse sup.

  • Das isinstance(obj, Class)Die boolesche Funktion gibt true zurück, wenn obj eine Instanz der Klasse Class oder eine Instanz einer Unterklasse der Klasse ist

Methoden überschreiben

Sie können Ihre übergeordneten Klassenmethoden jederzeit überschreiben. Ein Grund für das Überschreiben der Methoden der Eltern ist, dass Sie möglicherweise spezielle oder andere Funktionen in Ihrer Unterklasse wünschen.

Beispiel

#!/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

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

Calling child method

Methoden zur Überladung der Basis

In der folgenden Tabelle sind einige allgemeine Funktionen aufgeführt, die Sie in Ihren eigenen Klassen überschreiben können.

Sr.Nr. Methode, Beschreibung & Beispielaufruf
1

__init__ ( self [,args...] )

Konstruktor (mit optionalen Argumenten)

Beispielaufruf: obj = className (args)

2

__del__( self )

Destruktor, löscht ein Objekt

Beispielanruf: del obj

3

__repr__( self )

Auswertbare Zeichenfolgendarstellung

Beispielanruf: repr (obj)

4

__str__( self )

Druckbare Zeichenfolgendarstellung

Beispielaufruf: str (obj)

5

__cmp__ ( self, x )

Objektvergleich

Beispielaufruf: cmp (obj, x)

Überladen von Operatoren

Angenommen, Sie haben eine Vektorklasse erstellt, um zweidimensionale Vektoren darzustellen. Was passiert, wenn Sie sie mit dem Plus-Operator hinzufügen? Höchstwahrscheinlich wird Python dich anschreien.

Sie können jedoch die __add__ -Methode in Ihrer Klasse definieren, um eine Vektoraddition durchzuführen, und dann würde sich der Plus-Operator erwartungsgemäß verhalten -

Beispiel

#!/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

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

Vector(7,8)

Ausblenden von Daten

Die Attribute eines Objekts können außerhalb der Klassendefinition sichtbar sein oder nicht. Sie müssen Attribute mit einem doppelten Unterstrich benennen, und diese Attribute sind dann für Außenstehende nicht direkt sichtbar.

Beispiel

#!/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

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

1
2
Traceback (most recent call last):
   File "test.py", line 12, in <module>
      print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'

Python schützt diese Mitglieder, indem der Name intern so geändert wird, dass er den Klassennamen enthält. Sie können auf Attribute wie object._className__attrName zugreifen . Wenn Sie Ihre letzte Zeile wie folgt ersetzen würden, dann funktioniert es für Sie -

.........................
print counter._JustCounter__secretCount

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

1
2
2