Exkurs - Datenkapselung in Python
Öffentliche / private Attribute
Ein Attribut wird in Python zu einem privaten Attribut, wenn der Attributname mit zwei Unterstrichen beginnt und nicht mit Unterstrichen endet. Beginnt der Attributname nicht mit einem Unterstrich, so ist das Attribut öffentlich.
Zur Verdeutlichung betrachten wir die folgende Implementierung der Klasse Roboter
:
class Roboter(object):
def __init__(self):
self.__x = 0
self.__y = 0
self.__r = 'S'
def schritt(self):
if self.__r == 'O':
self.__x = self.__x + 1
elif self.__r == 'S':
self.__y = self.__y + 1
elif self.__r == 'W':
self.__x = self.__x - 1
elif self.__r == 'N':
self.__y = self.__y - 1
def rechts(self):
# ...
def links(self):
# ...
def getX(self):
return self.__x
def getY(self):
return self.__y
def getR(self):
return self.__r
def getZustand(self):
return (self.__x, self.__y, self.__r)
def setZustand(self, x, y, r):
self.__x = x
self.__y = y
self.__r = r
Beachte, dass die Attribute __x
, __y
und __r
hier alle private Attribute sind.
Zugriffsmethoden
Zugriffsmethoden benötigt man, um (ohne Insiderwissen) auf private Attribute lesend und schreibend zugreifen zu können. Das Programm oben zeigt, wie man solche Methoden implementiert.
Solche Zugriffsmethoden benutzt man, um z. B. privaten Attribut Werte zuzuweisen und um diese Werte anschließend auszulesen.
>>> rob = Roboter()
>>> rob.setZustand(2, 3, 'O')
>>> rob.getZustand()
(2, 3, 'O')
>>> rob.schritt()
>>> rob.schritt()
>>> rob.getX()
4
>>> rob.getY()
3
Achtung: Python-Besonderheiten
Python verhält sich bei privaten Attributen (leider) nicht so restriktiv, wie das eigentlich sein sollte. Der folgende Python-Dialog zeigt einige Besonderheiten von Python.
>>> rob = Roboter()
>>> rob.__x
Traceback (most recent call last):
File ...
rob.__x
AttributeError: 'Roboter' object has no attribute '__x'
>>> rob.__dict__
{'_Roboter__y': 0, '_Roboter__x': 0, '_Roboter__r': 'S'}
>>> rob._Roboter__x
0
Wie erwartet kann man auf das private Attribut __x
des neu erzeugten Objekts rob
nicht zugreifen. Python meldet als Fehler, dass es kein Attribut __x
gibt.
Der Aufruf rob.__dict__
verrät, woran das liegt. Ein Aufruf wie rob.__dict__
listet sämtliche Attribute mit den zugehörigen Attributwerten des betreffenden Objekts auf.
Interessant ist hier, dass sich das private Attribut __x
hinter einem anderen Namen versteckt.
Wenn man weiß, wie der neue Name - hier _Roboter__x
- gebildet wird, dann kann man
durchaus auf das betreffende Attribut zugreifen.
Also: Private Attribute werden in Python mit anderen Namen versehen, so dass kein direkter Zugriff möglich ist.
Kennt man den Namen, hinter dem sich ein privates Attribut verbirgt, so kann man durchaus auf dieses Attribut
zugreifen. Python liefert keinen echten Zugriffsschutz.
Die völlig unrestiktive Art von Python kann zu unerwartetem Verhalten von Objekten und sehr schwer zu findenden Fehlern führen. Der folgende Dialog zeigt ein solches Beispiel.
>>> rob = Roboter()
>>> rob.__x
Traceback (most recent call last):
File ...
rob.__x
AttributeError: 'Roboter' object has no attribute '__x'
>>> rob.__dict__
{'_Roboter__y': 0, '_Roboter__x': 0, '_Roboter__r': 'S'}
>>> rob.__x = 4
>>> rob.__x
4
>>> rob.__dict__
{'_Roboter__y': 0, '_Roboter__x': 0, '_Roboter__r': 'S', '__x': 4}
Ein erster Zugriff auf das private Attribut __x
scheitert. Dann aber ist es - entgegen aller
Zugriffslogik - scheinbar möglich, dem privaten Attribut __x
einen Wert zuzuweisen.
Der Aufruf w.__dict__
erklärt erst, was hier passiert ist. Neben dem privaten Attribut __x
,
das sich hinter dem neuen Namen _Roboter__x
versteckt, gibt es noch
ein weiteres öffentliches Attribut __x
, auf das man direkt zugreifen kann.
Das Beispiel zeigt, dass man in Python am besten klare Regeln befolgt, um nicht zu solch undurchschaubaren Objektsituationen zu gelangen.
Vereinbarung: Umgang mit privaten Attributen und Methoden
Wir werden im Folgenden bei der Implementierung von Klassen in Python keine Attribute und Methoden als privat deklarieren. Alle Attribute und Methoden sind daher direkt zugänglich. Allerdings werden wir von dem direkten Zugriff nicht immer Gebrauch machen. In der Regel werden wir keinen schreibenden Zugriff auf Attribute vornehmen. Zur Veränderung von Attributwerten sollen immer geeignete Methoden vorgesehen. Nur in begründeten Sonderfällen (z.B. zum schnellen Testen) weichen wir von dieser Vereinbarung ab.