5.1 Zugriffsmodifikatoren
Du hast wahrscheinlich den seltsamen Namen des Konstruktors __init__ bemerkt? In Zukunft wirst du sowas ziemlich oft sehen.
In Python gibt es verschiedene Zugriffsebenen für Attribute und Methoden von Klassen, die helfen, die Sichtbarkeit und den Schutz von Daten zu kontrollieren. Die Hauptmethoden zur Verwaltung des Zugriffs umfassen die Verwendung eines oder zweier Unterstriche (_ und __) vor dem Namen des Attributs oder der Methode.
Verwendung von Konventionen
Ein Unterstrich _ wird für Attribute und Methoden verwendet, die nicht außerhalb der Klasse oder des Moduls verwendet werden sollten. Das ist nicht verboten, aber es ist eine Konvention, die befolgt werden sollte für bessere Lesbarkeit und Wartung des Codes.
Zwei Unterstriche __ werden für Attribute und Methoden verwendet, die wirklich privat und geschützt sein sollten vor unbeabsichtigtem oder absichtlichem Zugriff von außen. Der Mechanismus name mangling macht sie weniger zugänglich, aber immer noch über spezielle Namen verfügbar.
Öffentliche (public) Felder und Methoden
Öffentliche Attribute und Methoden sind von überall im Code aus zugänglich. In Python sind standardmäßig alle Attribute und Methoden öffentlich, wenn ihre Namen nicht mit einem Unterstrich beginnen.
class MyClass:
def __init__(self):
self.public_attribute = "I am public"
def public_method(self):
return "This is a public method"
obj = MyClass()
print(obj.public_attribute) # Verfügbar
print(obj.public_method()) # Verfügbar
Durch Zugriffsebenen in der Sprache Python wird Inklusion realisiert, und zwar durch nicht öffentliche Felder und Methoden.
5.2 Nicht öffentliche Felder und Methoden
Geschützte (protected) Felder und Methoden
Geschützte Attribute und Methoden werden mit einem Unterstrich _ vor dem Namen gekennzeichnet und sind für die interne Verwendung in der Klasse und ihren Unterklassen bestimmt. Es ist eine Konvention, die Programmierern sagt, dass Daten nicht außerhalb der Klasse verwendet werden sollen.
class MyClass:
def __init__(self):
self._protected_attribute = "I am protected"
def _protected_method(self):
return "This is a protected method"
obj = MyClass()
print(obj._protected_attribute) # Verfügbar, aber nicht empfohlen
print(obj._protected_method()) # Verfügbar, aber nicht empfohlen
Private (private) Felder und Methoden
In Python werden private Attribute und Methoden mit zwei Unterstrichen __ vor dem Namen gekennzeichnet. Diese Attribute und Methoden sind ausschließlich zur Verwendung innerhalb der Klasse bestimmt, und ihr Hauptzweck besteht darin, die interne Implementierung zu verbergen und Daten vor unbeabsichtigter Änderung oder Nutzung von außen zu schützen.
Um den direkten Zugriff auf solche Attribute und Methoden von externem Code zu verhindern, wendet Python einen speziellen Mechanismus an, der als name mangling (Namensverzerrung) bekannt ist. Dieser Mechanismus ändert automatisch die Namen der privaten Attribute, indem er ihnen ein Präfix hinzufügt, das aus dem Klassennamen besteht. So wird das private Attribut __private_attribute in der Klasse MyClass in den internen Namen _MyClass__private_attribute umgewandelt.
Dies ermöglicht den Schutz der Daten vor unbeabsichtigtem Zugriff, während die Möglichkeit, mit ihnen innerhalb der Klasse zu arbeiten, erhalten bleibt. Es ist jedoch wichtig zu beachten, dass der Mechanismus "name mangling" keinen absoluten Schutz bietet — ein erfahrener Programmierer kann auf diese Daten zugreifen, indem er den veränderten Namen verwendet.
Lass uns sehen, wie das in der Praxis funktioniert:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
def __private_method(self):
return "This is a private method"
def access_private_method(self):
return self.__private_method()
obj = MyClass()
# print(obj.__private_attribute) # Fehler, nicht direkt verfügbar
# print(obj.__private_method()) # Fehler, nicht direkt verfügbar
print(obj.access_private_method()) # Verfügbar über eine öffentliche Klassenmethode
Wie aus dem Beispiel ersichtlich, führt der direkte Zugriff auf private Attribute oder Methoden zu einem Fehler. Aber Python behält die Möglichkeit, auf sie über den veränderten Namen zuzugreifen. Zum Beispiel kannst du auf das private Attribut mit dem "verfälschten" Namen zugreifen, wie unten gezeigt:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
obj = MyClass()
print(obj._MyClass__private_attribute) # Gibt aus: I am private
Auch wenn der Zugriff über den "verfälschten" Namen möglich ist, sollte dies vermieden werden, da es die Prinzipien der Inklusion verletzt und zur Instabilität des Codes führen kann.
Um zu sehen, wie Python Attributnamen ändert, kannst du die eingebaute Funktion dir() verwenden, die alle verfügbaren Attribute und Methoden eines Objekts anzeigt:
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
obj = MyClass()
print(dir(obj)) # Gibt alle Attribute und Methoden des Objekts aus, einschließlich "verfälschter" Namen
Bei der Ausführung der Funktion dir() wirst du eine Liste aller Attribute und Methoden des Objekts sehen, einschließlich _MyClass__private_attribute, was den Mechanismus "name mangling" bestätigt.
5.3 Automatische Methodenaufrufe
Es gab einen interessanten Aspekt bei der Arbeit mit Konstruktoren, den du möglicherweise bemerkt hast. Die Methode __init__ wurde automatisch aufgerufen.
Tatsächlich gibt es viele solcher Situationen sowie Methoden für diese Fälle. Beispiele:
Methode __str__
Wenn dein Objekt eine Methode __str__ hat, wird diese automatisch aufgerufen, wenn versucht wird, dein Objekt in einen String zu konvertieren, zum Beispiel bei der Verwendung von Funktionen print() und str().
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
cat = Cat("Barsik", 5)
print(cat) # Gibt aus: Barsik is 5 years old
Methode __len__
Und wenn dein Objekt eine Methode __len__ hat, wird diese automatisch aufgerufen, wenn versucht wird, die „Länge“ deines Objekts zu bestimmen - verwendet durch die Funktion len(). Beispiel:
class MyList:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
my_list = MyList([1, 2, 3])
print(len(my_list)) # Gibt aus: 3
Solche „spezielle Methoden“ werden noch viele in deinem Leben sein, aber die Arbeit mit ihnen macht großen Spaß. Also mach dich bereit :)
GO TO FULL VERSION