Python ist eine objektorientierte Sprache seit es sie gibt. Deshalb ist das Erstellen und Verwenden von Klassen und Objekten geradezu einfach. Dieses Kapitel hilft Ihnen, ein Experte im Umgang mit der objektorientierten 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 zu Rate ziehen, damit Sie die grundlegenden Konzepte beherrschen.
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
-
Klasse – Ein benutzerdefinierter Prototyp für ein Objekt, der eine Reihe von Attributen definiert, die jedes Objekt der Klasse charakterisieren. Die Attribute sind Datenmitglieder (Klassenvariablen und Instanzvariablen) und Methoden, auf die über die Punktnotation zugegriffen wird.
-
Klassenvariable – Eine Variable, die von allen Instanzen einer Klasse gemeinsam genutzt wird. Klassenvariablen werden innerhalb einer Klasse definiert, aber außerhalb der Methoden der Klasse. Klassenvariablen werden nicht so häufig verwendet wie Instanzvariablen.
-
Datenelement – Eine Klassenvariable oder Instanzvariable, die Daten enthält, die mit einer Klasse und ihren Objekten verbunden sind.
-
Funktionsüberladung – Die Zuweisung von mehr als einem Verhalten an eine bestimmte Funktion. Die durchgeführte Operation hängt von den Typen der beteiligten Objekte oder Argumente ab.
-
Instanzvariable – Eine Variable, die innerhalb einer Methode definiert ist und nur zur aktuellen Instanz einer Klasse gehört.
-
Vererbung – Die Übertragung der Eigenschaften einer Klasse auf andere Klassen, die von ihr abgeleitet sind.
-
Instanz – Ein einzelnes Objekt einer bestimmten Klasse. Ein Objekt obj, das zu einer Klasse Circle gehört, ist zum Beispiel eine Instanz der Klasse Circle.
-
Instantiierung – Die Erzeugung einer Instanz einer Klasse.
-
Methode – Eine spezielle Art von Funktion, die in einer Klassendefinition definiert ist.
-
Objekt – Eine eindeutige Instanz einer Datenstruktur, die durch ihre Klasse definiert ist. Ein Objekt umfasst sowohl Datenmitglieder (Klassenvariablen und Instanzvariablen) als auch Methoden.
-
Operatorüberladung – Die Zuweisung von mehr als einer Funktion an einen bestimmten Operator.
Erstellen von Klassen
Die class-Anweisung erstellt eine neue Klassendefinition. Der Name der Klasse folgt unmittelbar auf das Schlüsselwort class, gefolgt von einem Doppelpunkt wie folgt –
class ClassName: 'Optional class documentation string' class_suite
-
Die Klasse hat einen Dokumentationsstring, auf den über ClassName.__doc__ zugegriffen werden kann.
-
Die class_suite besteht aus allen Komponentenanweisungen, die Klassenmitglieder, Datenattribute und Funktionen definieren.
Beispiel
Nachfolgend 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 der Klasse gemeinsam genutzt wird. Auf sie kann als Employee.empCount von innerhalb oder außerhalb der Klasse zugegriffen werden.
-
Die erste Methode __init__() ist eine spezielle Methode, die als Klassenkonstruktor oder Initialisierungsmethode bezeichnet wird und die Python aufruft, wenn Sie eine neue Instanz dieser Klasse erstellen.
-
Sie deklarieren andere Klassenmethoden wie normale Funktionen, mit der Ausnahme, dass das erste Argument jeder Methode self ist. Python fügt das self-Argument für Sie in die Liste ein; Sie müssen es nicht einschließen, wenn Sie die Methoden aufrufen.
Erzeugen von Instanzobjekten
Um Instanzen einer Klasse zu erzeugen, rufen Sie die Klasse mit class name auf und übergeben die Argumente, die ihre __init__-Methode 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 Attribute des Objekts zu, indem Sie den Punktoperator mit object verwenden. Auf Klassenvariablen würde man mit dem Klassennamen wie folgt zugreifen –
emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount
Wenn man nun alle Konzepte zusammenfasst –
#!/usr/bin/pythonclass 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, ergibt sich folgendes Ergebnis –
Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2
Sie können Attribute von Klassen und Objekten hinzufügen, entfernen, 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 zu verwenden, um auf Attribute zuzugreifen, können Sie die folgenden Funktionen verwenden –
-
Das getattr(obj, name) – um auf das Attribut eines Objekts zuzugreifen.
-
Das hasattr(obj,name) – um zu prüfen, ob ein Attribut existiert oder nicht.
-
Das setattr(obj,name,value) – um ein Attribut zu setzen. Wenn das Attribut nicht existiert, dann wird es erstellt.
-
Delattr(obj, name) – um ein Attribut zu löschen.
hasattr(emp1, 'age') # Returns true if 'age' attribute existsgetattr(emp1, 'age') # Returns value of 'age' attributesetattr(emp1, 'age', 8) # Set attribute 'age' at 8delattr(empl, 'age') # Delete attribute 'age'
Eingebaute Klassenattribute
Jede Pythonklasse hat folgende eingebaute Attribute und auf sie kann mit dem Punktoperator wie auf jedes andere Attribut zugegriffen werden –
-
__dict__ – Wörterbuch, das den Namespace der Klasse enthält.
-
__doc__ – Klassendokumentationsstring oder keiner, wenn undefiniert.
-
__name__ – Klassenname.
-
__module__ – Modulname, in dem die Klasse definiert ist. Dieses Attribut ist „__main__“ im interaktiven Modus.
-
__bases__ – Ein möglicherweise leeres Tupel, das die Basisklassen enthält, in der Reihenfolge ihres Auftretens in der Basisklassenliste.
Für die obige Klasse wollen wir versuchen, auf alle diese Attribute zuzugreifen –
#!/usr/bin/pythonclass 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.salaryprint "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, ergibt sich folgendes Ergebnis –
Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__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 löschen (Garbage Collection)
Python löscht nicht benötigte Objekte (eingebaute Typen oder Klasseninstanzen) automatisch, um den Speicherplatz freizugeben. Der Prozess, durch den Python periodisch nicht mehr benötigte Speicherblöcke zurückfordert, wird als Garbage Collection bezeichnet.
Pythons Garbage Collector läuft während der Programmausführung und wird ausgelöst, wenn die Referenzzahl eines Objekts Null erreicht. Die Anzahl der Referenzen eines Objekts ändert sich, wenn sich die Anzahl der Aliase, die auf das Objekt verweisen, ändert.
Die Anzahl der Referenzen eines Objekts erhöht sich, wenn ihm ein neuer Name zugewiesen oder es in einen Container (Liste, Tupel oder Wörterbuch) eingefügt wird. Die Anzahl der Referenzen eines Objekts verringert sich, wenn es mit del gelöscht wird, seine Referenz neu zugewiesen wird oder seine Referenz den Gültigkeitsbereich verlässt. Wenn die Anzahl der Referenzen eines Objekts Null erreicht, sammelt Python es automatisch ein.
a = 40 # Create object <40>b = a # Increase ref. count of <40> c = # Increase ref. count of <40> del a # Decrease ref. count of <40>b = 100 # Decrease ref. count of <40> c = -1 # Decrease ref. count of <40>
Normalerweise werden Sie nicht bemerken, wenn der Garbage Collector eine verwaiste Instanz zerstört und ihren Platz zurückfordert. Aber eine Klasse kann eine spezielle Methode __del__() implementieren, die Destruktor genannt wird und aufgerufen wird, wenn die Instanz zerstört werden soll. Diese Methode kann verwendet werden, um alle nicht von einer Instanz verwendeten Speicherressourcen aufzuräumen.
Beispiel
Dieser __del__()-Destruktor gibt den Klassennamen einer Instanz aus, die kurz vor der Zerstörung steht –
#!/usr/bin/pythonclass 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 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3
Wenn der obige Code ausgeführt wird, erzeugt er folgendes Ergebnis –
3083401324 3083401324 3083401324Point destroyed
Hinweis – Idealerweise sollten Sie Ihre Klassen in einer separaten Datei definieren und sie dann in Ihre Hauptprogrammdatei mit Hilfe der import-Anweisung importieren.
Klassenvererbung
Anstatt ganz von vorne anzufangen, können Sie eine Klasse erstellen, indem Sie sie von einer bereits vorhandenen Klasse ableiten, indem Sie die Elternklasse in Klammern hinter dem Namen der neuen Klasse aufführen.
Die Kindklasse erbt die Attribute ihrer Elternklasse, und Sie können diese Attribute so verwenden, als ob sie in der Kindklasse definiert wären. Eine untergeordnete Klasse kann auch Datenelemente und Methoden der übergeordneten Klasse außer Kraft setzen.
Syntax
Abgeleitete Klassen werden ähnlich wie ihre Elternklasse deklariert; jedoch wird nach dem Klassennamen eine Liste von Basisklassen angegeben, von denen geerbt werden soll –
class SubClassName (ParentClass1): 'Optional class documentation string' class_suite
Beispiel
#!/usr/bin/pythonclass 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.parentAttrclass Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'c = Child() # instance of childc.childMethod() # child calls its methodc.parentMethod() # calls parent's methodc.setAttr(200) # again call parent's methodc.getAttr() # again call parent's method
Wenn der obige Code ausgeführt wird, ergibt sich folgendes Ergebnis –
Calling child constructorCalling child methodCalling parent methodParent attribute : 200
Auf ähnliche Weise kann man eine Klasse von mehreren Elternklassen wie folgt ableiten –
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() kann man eine Beziehung zwischen zwei Klassen und Instanzen überprüfen.
-
Die boolesche Funktion issubclass(sub, sup) gibt true zurück, wenn die angegebene Unterklasse sub tatsächlich eine Unterklasse der Oberklasse sup ist.
-
Die boolesche Funktion isinstance(obj, Class) gibt true zurück, wenn obj eine Instanz der Klasse Class oder eine Instanz einer Unterklasse von Class ist
Methoden überschreiben
Sie können die Methoden Ihrer Elternklasse immer überschreiben. Ein Grund für das Überschreiben der Methoden der Elternklasse ist, dass Sie vielleicht eine spezielle oder andere Funktionalität in Ihrer Unterklasse wünschen.
Beispiel
#!/usr/bin/pythonclass 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 childc.myMethod() # child calls overridden method
Wenn der obige Code ausgeführt wird, ergibt sich folgendes Ergebnis –
Calling child method
Base Overloading Methods
Die folgende Tabelle listet einige generische Funktionen auf, die Sie in Ihren eigenen Klassen überschreiben können –
Sr.No. | Methode, Beschreibung &Beispielaufruf |
---|---|
1 |
__init__ ( self ) Konstruktor (mit beliebigen optionalen Argumenten) Beispielaufruf : obj = className(args) |
2 |
__del__( self ) Destructor, löscht ein Objekt Beispielaufruf : del obj |
3 |
__repr__( self ) Auswertbare Stringdarstellung Beispielaufruf : repr(obj) |
4 |
__str__( self ) Druckbare Stringdarstellung Beispielaufruf : str(obj) |
5 |
__cmp__ ( self, x ) Objektvergleich Beispielaufruf : cmp(obj, x) |
Overloading Operators
Angenommen, Sie haben eine Vector-Klasse erstellt, um zweidimensionale Vektoren darzustellen, was passiert, wenn Sie den Plus-Operator verwenden, um sie zu addieren? Höchstwahrscheinlich wird Python Sie anschreien.
Sie könnten jedoch die __add__-Methode in Ihrer Klasse definieren, um die Vektoraddition durchzuführen, und dann würde sich der Plus-Operator wie erwartet verhalten –
Beispiel
#!/usr/bin/pythonclass 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, führt er zu folgendem Ergebnis –
Vector(7,8)
Data Hiding
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 nicht direkt für Außenstehende sichtbar.
Beispiel
#!/usr/bin/pythonclass JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCountcounter = JustCounter()counter.count()counter.count()print counter.__secretCount
Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis –
12Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'
Python schützt diese Mitglieder, indem es intern den Namen so ändert, dass er den Klassennamen enthält. Sie können auf solche Attribute als object._className__attrName zugreifen. Wenn Sie Ihre letzte Zeile wie folgt ersetzen, dann funktioniert es für Sie –
.........................print counter._JustCounter__secretCount
Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis –