Objektorientiertes Python

Python ist seit seinem Entwurf eine objektorientierte Sprache. Aus diesem Grund ist es sehr einfach, Klassen und Objekte in Python zu erstellen. In diesem Kapitel stellen wir Pythons objektorientierte Programmierung ausführlich vor.

Wenn Sie zuvor noch nicht mit objektorientierten Programmiersprachen in Berührung gekommen sind, sollten Sie zunächst einige grundlegende Merkmale objektorientierter Sprachen kennenlernen und in Ihrem Kopf ein grundlegendes Konzept der Objektorientierung entwickeln; dies wird Ihnen helfen, Pythons objektorientierte Programmierung leichter zu erlernen.

Betrachten wir als Nächstes kurz einige grundlegende Merkmale der Objektorientierung.


Einführung in die objektorientierte Technologie

  • Klasse:Wird verwendet, um eine Sammlung von Objekten mit denselben Attributen und Methoden zu beschreiben. Sie definiert die Attribute und Methoden, die jedem Objekt in der Sammlung gemeinsam sind. Objekte sind Instanzen von Klassen.
  • Klassenvariable:Klassenvariablen werden von allen instanziierten Objekten gemeinsam genutzt. Klassenvariablen werden innerhalb der Klasse und außerhalb eines beliebigen Funktionsrumpfs definiert. Klassenvariablen werden normalerweise nicht als Instanzvariablen verwendet.
  • Datenmitglieder:Klassenvariablen oder Instanzvariablen, die verwendet werden, um Daten im Zusammenhang mit der Klasse und ihren Instanzobjekten zu verarbeiten.
  • Methodenüberschreibung:Wenn eine von der Elternklasse geerbte Methode die Anforderungen der Kindklasse nicht erfüllen kann, kann sie überschrieben werden. Dieser Vorgang wird als Methodenüberschreibung bezeichnet.
  • Lokale Variablen:In Methoden definierte Variablen, die sich nur auf die Klasse der aktuellen Instanz auswirken.
  • Instanzvariablen:In der Klassendeklaration werden Attribute durch Variablen dargestellt. Solche Variablen werden Instanzvariablen genannt; sie werden innerhalb der Klassendeklaration, aber außerhalb der anderen Membermethoden der Klasse deklariert.
  • Vererbung:Das heißt, eine abgeleitete Klasse erbt die Felder und Methoden einer Basisklasse. Vererbung ermöglicht es außerdem, ein Objekt einer abgeleiteten Klasse als Objekt einer Basisklasse zu behandeln. Zum Beispiel gibt es ein Design: Ein Objekt vom Typ Dog leitet sich von der Klasse Animal ab, was eine "ist-ein"-Beziehung simuliert (z. B. Dog ist ein Animal).
  • Instanziierung:Erstellen einer Instanz einer Klasse, des konkreten Objekts der Klasse.
  • Methode:Eine in einer Klasse definierte Funktion.
  • Objekt:Eine Instanz einer Datenstruktur, die durch eine Klasse definiert wird. Objekte enthalten zwei Datenelemente (Klassenvariablen und Instanzvariablen) und Methoden.

Klassen erstellen

Verwenden Sie die class-Anweisung, um eine neue Klasse zu erstellen. Nach class folgt der Klassenname und endet mit einem Doppelpunkt:

class ClassName:
   '类的帮助信息'   #类文档字符串
   class_suite  #类体

Die Hilfeinformationen der Klasse können über ClassName.__doc__ angezeigt werden.

class_suite besteht aus Klassenmitgliedern, Methoden und Datenattributen.

Beispiel

Das folgende ist ein einfaches Beispiel einer Python-Klasse:

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Basisklasse für alle Mitarbeiter' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Mitarbeiter insgesamt %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Gehalt: ", self.salary
  • Die Variable empCount ist eine Klassenvariable, deren Wert von allen Instanzen dieser Klasse gemeinsam genutzt wird. Sie können über Employee.empCount innerhalb der Klasse oder außerhalb der Klasse darauf zugreifen.

  • Die erste Methode, __init__(), ist eine spezielle Methode, die Klassenkonstruktor oder Initialisierungsmethode genannt wird. Diese Methode wird aufgerufen, wenn eine Instanz der Klasse erstellt wird.

  • self repräsentiert eine Instanz der Klasse. self ist erforderlich, wenn Klassenmethoden definiert werden, obwohl der entsprechende Parameter beim Aufruf nicht übergeben werden muss.

self repräsentiert eine Instanz der Klasse, nicht die Klasse

Klassenmethoden unterscheiden sich nur in einem besonderen Punkt von gewöhnlichen Funktionen – sie müssen einen zusätzlichenersten Parameter haben, dessen Name konventionell self ist.

class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()

Das Ausführungsergebnis des obigen Beispiels ist:

<__main__.Test instance at 0x10d066878>
__main__.Test

Aus dem Ausführungsergebnis ist sehr deutlich, dass self die Instanz der Klasse repräsentiert, die Adresse des aktuellen Objekts darstellt, währendself.__class__auf die Klasse verweist.

self ist kein Python-Schlüsselwort. Wir können es durch example ersetzen, und es wird trotzdem normal ausgeführt:

Beispiel

class Test: def prt(example): print(example) print(example.__class__) t = Test() t.prt()

Das Ausführungsergebnis des obigen Beispiels ist:

<__main__.Test instance at 0x10d066878>
__main__.Test

Instanzobjekte erstellen

Beim Instanziieren einer Klasse verwenden andere Programmiersprachen im Allgemeinen das Schlüsselwort new, aber in Python gibt es dieses Schlüsselwort nicht. Die Klasseninstanziierung ähnelt einem Funktionsaufruf.

Im Folgenden wird der Klassenname Employee zur Instanziierung verwendet und Parameter werden über die __init__-Methode empfangen.

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)

Zugriff auf Attribute

Sie können den Punkt.verwenden, um auf die Attribute des Objekts zuzugreifen. Verwenden Sie den Klassennamen wie folgt, um auf Klassenvariablen zuzugreifen:

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

Vollständiges Beispiel:

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Basisklasse für alle Mitarbeiter' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Mitarbeiter insgesamt %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Gehalt: ", self.salary "Erstellen Sie das erste Objekt der Klasse Employee" emp1 = Employee("Zara", 2000) "Erstellen Sie das zweite Objekt der Klasse Employee" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Mitarbeiter insgesamt %d" % Employee.empCount

Die Ausgabe der Ausführung des obigen Codes lautet wie folgt:

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

Sie können Klassenattribute wie unten gezeigt hinzufügen, löschen und ändern:

emp1.age = 7  # 添加一个 'age' 属性
emp1.age = 8  # 修改 'age' 属性
del emp1.age  # 删除 'age' 属性

Sie können auch die folgenden Funktionen verwenden, um auf Attribute zuzugreifen:

  • getattr(obj, name[, default]) : Greift auf das Attribut des Objekts zu.
  • hasattr(obj,name) : Prüft, ob ein Attribut vorhanden ist.
  • setattr(obj,name,value) : Setzt ein Attribut. Wenn das Attribut nicht existiert, wird ein neues Attribut erstellt.
  • delattr(obj, name) : Löscht das Attribut.
hasattr(emp1, 'age') # Gibt True zurück, wenn das Attribut 'age' existiert. getattr(emp1, 'age') # Gibt den Wert des Attributs 'age' zurück setattr(emp1, 'age', 8) # Fügt das Attribut 'age' mit dem Wert 8 hinzu delattr(emp1, 'age') # Löscht das Attribut 'age'

Integrierte Klassenattribute von Python

  • __dict__ : Die Attribute der Klasse (enthält ein Dictionary, das aus den Datenattributen der Klasse besteht)
  • __doc__ : Der Docstring der Klasse
  • __name__: Klassenname
  • __module__: Das Modul, in dem die Klasse definiert ist (der vollständige Name der Klasse ist '__main__.className'; wenn die Klasse in einem importierten Modul mymod liegt, dann entspricht className.__module__ dem mymod)
  • __bases__ : Die Elemente, die alle Elternklassen der Klasse bilden (enthält ein Tupel, das aus allen Elternklassen besteht)

Das folgende Beispiel zeigt den Aufruf der integrierten Klassenattribute von Python:

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Basisklasse für alle Mitarbeiter' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Mitarbeiter insgesamt %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Gehalt: ", 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__

Die Ausgabe der Ausführung des obigen Codes lautet wie folgt:

Employee.__doc__: 所有员工的基类
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}

Python-Objektzerstörung (Garbage Collection)

Python verwendet die einfache Technik der Referenzzählung, um Müll zu verfolgen und zurückzugewinnen.

Intern zeichnet Python auf, wie viele Referenzen für alle verwendeten Objekte existieren.

Eine interne Verfolgungsvariable, genannt Referenzzähler.

Wenn ein Objekt erstellt wird, wird ein Referenzzählwert erstellt. Wenn dieses Objekt nicht mehr benötigt wird, d. h. wenn der Referenzzählwert des Objekts 0 wird, wird es durch Garbage Collection gesammelt. Die Sammlung erfolgt jedoch nicht "sofort"; der Interpreter gibt den vom Müllobjekt belegten Speicherplatz zu einem geeigneten Zeitpunkt frei.

a = 40      # 创建对象  <40>
b = a       # 增加引用, <40> 的计数
c = [b]     # 增加引用.  <40> 的计数

del a       # 减少引用 <40> 的计数
b = 100     # 减少引用 <40> 的计数
c[0] = -1   # 减少引用 <40> 的计数

Der Garbage-Collection-Mechanismus zielt nicht nur auf Objekte mit einem Referenzzählwert von 0 ab, sondern kann auch zirkuläre Referenzen verarbeiten. Zirkuläre Referenzen beziehen sich auf zwei Objekte, die sich gegenseitig referenzieren, aber auf die keine anderen Variablen verweisen. In diesem Fall ist es nicht ausreichend, sich nur auf die Referenzzählung zu verlassen. Pythons Garbage Collector ist tatsächlich ein Referenzzähler und ein zirkulärer Garbage Collector. Als Ergänzung zur Referenzzählung behält der Garbage Collector auch Objekte mit einer großen Gesamtzuweisung im Auge (d. h. solche, die nicht durch Referenzzählung zerstört werden). In solchen Fällen hält der Interpreter an und versucht, alle nicht referenzierten Zyklen zu bereinigen.

Beispiel

Der Destruktor __del__ wird aufgerufen, wenn das Objekt zerstört wird. Wenn das Objekt nicht mehr verwendet wird, läuft die __del__-Methode:

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- 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) # Print the object's id del pt1 del pt2 del pt3

Das Ausführungsergebnis des obigen Beispiels ist wie folgt:

3083401324 3083401324 3083401324
Point 销毁

Hinweis:Normalerweise müssen Sie eine Klasse in einer separaten Datei definieren,

Klassenvererbung

Einer der Hauptvorteile der objektorientierten Programmierung ist die Wiederverwendung von Code, und eine Möglichkeit, diese Wiederverwendung zu erreichen, ist der Vererbungsmechanismus.

Die durch Vererbung erzeugte neue Klasse wird alsUnterklasseoderabgeleitete Klassebezeichnet, und die Klasse, von der geerbt wird, wird alsBasisklasse、ElternklasseoderSuperklasse。

Vererbungssyntax

class 派生类名(基类名)
    ...

Einige Merkmale der Vererbung in Python:

  • 1. Wenn der Konstruktor der Elternklasse in der Unterklasse benötigt wird, müssen Sie den Konstruktor der Elternklasse explizit aufrufen oder den Konstruktor der Elternklasse nicht überschreiben. Details siehe:Erklärung zur Python-Unterklasse, die den Konstruktor der Elternklasse erbt。
  • 2. Beim Aufruf einer Methode der Basisklasse müssen Sie ihr den Namen der Basisklasse voranstellen und die Parametervariable self angeben. Der Unterschied besteht darin, dass Sie beim Aufruf gewöhnlicher Funktionen innerhalb einer Klasse die Parametervariable self nicht angeben müssen.
  • 3. Python sucht immer zuerst nach der entsprechenden Art von Methode. Wenn die entsprechende Methode in der abgeleiteten Klasse nicht gefunden werden kann, sucht es anschließend eine nach der anderen in den Basisklassen. (Es sucht zuerst nach der aufgerufenen Methode in der aktuellen Klasse und geht nur dann zur Basisklasse, wenn sie nicht gefunden wird.)

Wenn mehr als eine Klasse im Vererbungs-Tupel aufgeführt ist, wird dies als "Mehrfachvererbung" bezeichnet.

Syntax:

Die Deklaration einer abgeleiteten Klasse ähnelt der ihrer Elternklasse. Die Liste der geerbten Basisklassen folgt auf den Klassennamen, wie unten gezeigt:

class SubClassName (ParentClass1[, ParentClass2, ...]):
    ...

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # Elternklasse definieren parentAttr = 100 def __init__(self): print "Rufe den Konstruktor der Elternklasse auf" def parentMethod(self): print 'Rufe eine Methode der Elternklasse auf' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Attribut der Elternklasse:", Parent.parentAttr class Child(Parent): # Unterklasse definieren def __init__(self): print "Rufe den Konstruktor der Unterklasse auf" def childMethod(self): print 'Rufe eine Methode der Unterklasse auf' c = Child() # Unterklasse instanziieren c.childMethod() # Rufe eine Methode der Unterklasse auf c.parentMethod() # Rufe eine Methode der Elternklasse auf c.setAttr(200) # Rufe erneut eine Methode der Elternklasse auf - setze Attributwert c.getAttr() # Rufe erneut eine Methode der Elternklasse auf - Attributwert abrufen

Die Ausgabe des obigen Codes lautet:

调用子类构造方法
调用子类方法
调用父类方法
父类属性 : 200

Sie können von mehreren Klassen erben

class A:        # 定义类 A
.....

class B:         # 定义类 B
.....

class C(A, B):   # 继承类 A 和 B
.....

Sie können die Methoden issubclass() oder isinstance() verwenden, um dies zu überprüfen.

  • issubclass() - Eine boolesche Funktion, die bestimmt, ob eine Klasse eine Unterklasse oder ein Nachkomme einer anderen Klasse ist. Syntax: issubclass(sub, sup)
  • isinstance(obj, Class) Eine boolesche Funktion, die true zurückgibt, wenn obj ein Instanzobjekt der Klasse Class oder ein Instanzobjekt einer Unterklasse von Class ist.

Methodenüberschreibung

Wenn die Funktionalität der Methode Ihrer Elternklasse Ihren Anforderungen nicht entspricht, können Sie die Methode der Elternklasse in der Unterklasse überschreiben:

Beispiel:

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # Elternklasse definieren def myMethod(self): print 'Methode der Elternklasse aufrufen' class Child(Parent): # Unterklasse definieren def myMethod(self): print 'Methode der Unterklasse aufrufen' c = Child() # Instanz der Unterklasse c.myMethod() # Unterklasse ruft die überschriebene Methode auf

Nach Ausführung des obigen Codes lautet die Ausgabe wie folgt:

Calling subclass methods

Grundlegende Überladungsmethoden

Die folgende Tabelle listet einige häufige Funktionen auf, die Sie in Ihren eigenen Klassen überschreiben können:

Nein.Methode, Beschreibung & Einfacher Aufruf
1__init__ ( self [,args...] )
Konstruktor
Einfacher Aufruf der Methode:obj = className(args)
2__del__( self )
Destruktor-Methode, löscht ein Objekt
Einfacher Aufruf der Methode:del obj
3__repr__( self )
In eine für den Interpreter lesbare Form umwandeln
Einfacher Aufruf der Methode:repr(obj)
4__str__( self )
Wird verwendet, um einen Wert in eine für Menschen lesbare Form umzuwandeln
Einfacher Methodenaufruf:str(obj)
5__cmp__ ( self, x )
Objektvergleich
Einfacher Methodenaufruf:cmp(obj, x)

Operatorüberladung

Python unterstützt auch Operatorüberladung, wie im folgenden Beispiel gezeigt:

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

Die Ausgabe des obigen Codes lautet:

Vector(7,8)

Klassenattribute und Methoden

Private Attribute einer Klasse

__private_attrs: Zwei führende Unterstriche deklarieren das Attribut als privat; es kann außerhalb der Klasse nicht verwendet oder direkt darauf zugegriffen werden. Wenn es innerhalb von Methoden in der Klasse verwendet wird,self.__private_attrs。

Methoden einer Klasse

Verwenden Sie innerhalb der Klasse das Schlüsselwortdef, um eine Methode für die Klasse zu definieren. Im Gegensatz zu gewöhnlichen Funktionsdefinitionen muss eine Klassenmethode den Parameter self als ersten Parameter enthalten.

Private Methoden einer Klasse

__private_method: Zwei führende Unterstriche deklarieren die Methode als privat; sie kann außerhalb der Klasse nicht aufgerufen werden. Um sie innerhalb der Klasse aufzurufen,self.__private_methods

Beispiel

#!/usr/bin/python # -*- coding: UTF-8 -*- class JustCounter: __secretCount = 0 # Private Variable publicCount = 0 # Öffentliche Variable def count(self): self.__secretCount += 1 self.publicCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.publicCount print counter.__secretCount # Fehler, eine Instanz kann nicht auf eine private Variable zugreifen

Python ändert den Namen so, dass er den Klassennamen enthält:

1
2
2
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    print counter.__secretCount  # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'

Python erlaubt es Klasseninstanzen nicht, auf private Daten zuzugreifen, aber Sie könnenobject._className__attrName( object_name._class_name__private_attribute_name) verwenden, um auf das Attribut zuzugreifen. Siehe das folgende Beispiel:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Example:
    __site = "www.example.com"

example = Example()
print example._Example__site

Führen Sie den obigen Code aus, und das Ergebnis ist wie folgt:

www.example.com

Erklärung von einfachem Unterstrich, doppeltem Unterstrich und doppeltem Unterstrich am Anfang und Ende:

  • __foo__: Definiert spezielle Methoden, normalerweise systemdefinierte Namen, wie__init__()und so weiter.

  • _foo: Eine Variable, die mit einem einzelnen Unterstrich beginnt, stellt eine geschützte Typvariable dar, das heißt, auf den geschützten Typ kann nur von sich selbst und Unterklassen zugegriffen werden, und sie kann nicht fürfrom module import * verwendet werden.

  • __foo: Doppelte Unterstriche kennzeichnen eine private Typvariable, auf die nur von der Klasse selbst zugegriffen werden kann.

Weitere Erweiterungen