Pythons OOP erklärt

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
BlackJack

XtraNine hat geschrieben:Das heißt wenn ich in Klasse A ein Attribut habe das zwei unterstriche am Anfang hat und dann die Klasse A in Klasse B vererbe, kann ich dann von Klasse B nicht auf das Attribut mit den 2 unterstrichen zugreifen weil es Protected ist (um mal die Analogie von C++ zu benutzen)?
Du kannst jedenfalls nicht einfach über den Namen darauf zugreifen wie in A.
Es wird ein Unterstrich und der Klassenname vor den Namen gesetzt.
Das verstehe ich nicht so ganz wie du das meinst. Meinst du folgendes?

Code: Alles auswählen

class KlasseA:
         def __init__ (self):
         _KlasseA_PrivatesAtribut = "test"
Sozusagen. Da fehlt noch ein Unterstrich zwischen Klassennamen und `PrivatesAtribut` aber das ist es was der Interpretierer für Dich macht, wenn Du zwei Unterstriche benutzt. Das schöne an Python ist ja das man alles "live" ausprobieren kann:

Code: Alles auswählen

In [5]: class A:
   ...:     def __init__(self):
   ...:         self.__test = 42
   ...:     def __str__(self):
   ...:         return str(self.__test)
   ...:

In [6]: a = A()

In [7]: print a
42

In [8]: a.__test
---------------------------------------------------------------------------
exceptions.AttributeError     Traceback (most recent call last)

/home/marc/<ipython console>

AttributeError: A instance has no attribute '__test'

In [9]: dir(a)
Out[9]: ['_A__test', '__doc__', '__init__', '__module__', '__str__']

In [10]: a._A__test
Out[10]: 42

In [11]: getattr(a, '_%s__%s' % (a.__class__.__name__, 'test'))
Out[11]: 42
Die letzte Eingabezeile zeigt wie man auf ein "privates" Attribut zugreifen kann, wenn man die Klasse von `a` nicht kennt, aber weiss es gibt ein `__test` in dieser Klasse.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Sorry das ich mich jetzt erst melde.

Danke dir für die vielen Beispiele :)

lg
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Es ist eigentlich ganz einfach: Du verzichtest auf Getter und Setter und greifst von außen ('public') immer direkt auf die Attribute zu. Willst du dabei abstrahieren, Werte prüfen oder sonst etwas tun, benutzt du property(). Das tolle ist ja, dass du nachträglich Getter/Setter bauen kannst, ohne die API zu verändern, aber nicht bereits im Vorfeld den Code mit Gettern und Settern aufblasen musst wie etwa in Java. Allein das Vorhandensein von IDE-Funktionen zum Erzeugen dieser zeigt einmal mehr, dass Java nur mit einer guten IDE effektiv zu beherrschen ist.

Sehr lesenswert dazu ist der Artikel Getters/Setters/Fuxors von Ryan Tomayko. Auch PJE schreibt dazu in Python Is Not Java:
Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans. Do not write getters and setters. This is what the 'property' built-in is for. And do not take that to mean that you should write getters and setters, and then wrap them in 'property'. That means that until you prove that you need anything more than a simple attribute access, don't write getters and setters. They are a waste of CPU time, but more important, they are a waste of programmer time. Not just for the people writing the code and tests, but for the people who have to read and understand them as well.

In Java, you have to use getters and setters because using public fields gives you no opportunity to go back and change your mind later to using getters and setters. So in Java, you might as well get the chore out of the way up front. In Python, this is silly, because you can start with a normal attribute and change your mind at any time, without affecting any clients of the class. So, don't write getters and setters.

In Python gibt es diese strikten Verbote wie private und protected nicht, alles ist zugreifbar. Ich denke, es macht auch Sinn, dass der Programmierer es *kann*, etwa um einen Fehler in einer verbreiteten Bibliothek mit einem Workaround zu umgehen. Aber im Normalfall wird er eben nur auf die dokumentierten Funktionen und Methoden zugreifen, wie er sie eben braucht. Alles eine Sache der Konvention, vgl. auch das Fehlen von Interfaces und abstrakten Klassen in Python (lassen sich bei Bedarf einfach nachbilden und es existiert ein verbreitetes Interfaces-Modul, das in Zope entstanden ist).
Antworten