Anfängerkurs in Python bei Coursera
mal ganz sachlich betrachtet: was gewinne ich, wenn ich auf Attribute mit einem Getter zugreife?
- z.B: »game.get_level()«, heißt soviel wie, oh dafür gibt es eine Funktion, also darf ich das Attribut auch lesen.
Das sagt mir aber noch nicht, dass das für meinen Anwendungsfall auch sinnvoll ist. Genauso gut könnte ich auch direkt »game.level« schreiben und in die Klassendokumentation schreiben, dass »level« ein öffentliches Attribut ist und dies und das bedeutet.
Was kann ich falsch machen? Ich kann mich verschreiben, was in beiden Fällen zu einem AttributeError führt.
Fazit: ein Getter bietet mir keinen Vorteil, es führt nur zu umständlicherem, komplexerem und langsamerem Code.
Nun zu den Settern: »game.set_level(3)«. Wenn es diese Methode nicht gibt, heißt das soviel wie, das Attribut ist von außen read-only. Aber das kann ich genauso gut erreichen, wenn ich in die Dokumentation hinter »level« „read-only“ schreibe. Wenn sich dann jemand nicht daran hält, wird er schon genau wissen, was er tut, oder eben nicht, dann ist ihm aber auch nicht mehr zu helfen.
Wenn ich mich beim Setzen verschreibe kann das zu schwer auffindbaren Fehlern führen, weil das Problem nicht sofort gemeldet wird. Ein falsch geschriebener Setter meldet sich sofort mit einem AttributeError. Andererseits sollten Programmteile sowieso nicht so komplex und nicht getestet sein, dass sich ein solcher Fehler lange verstecken kann.
Fazit: auch Setter haben nicht wirklich einen Vorteil.
- z.B: »game.get_level()«, heißt soviel wie, oh dafür gibt es eine Funktion, also darf ich das Attribut auch lesen.
Das sagt mir aber noch nicht, dass das für meinen Anwendungsfall auch sinnvoll ist. Genauso gut könnte ich auch direkt »game.level« schreiben und in die Klassendokumentation schreiben, dass »level« ein öffentliches Attribut ist und dies und das bedeutet.
Was kann ich falsch machen? Ich kann mich verschreiben, was in beiden Fällen zu einem AttributeError führt.
Fazit: ein Getter bietet mir keinen Vorteil, es führt nur zu umständlicherem, komplexerem und langsamerem Code.
Nun zu den Settern: »game.set_level(3)«. Wenn es diese Methode nicht gibt, heißt das soviel wie, das Attribut ist von außen read-only. Aber das kann ich genauso gut erreichen, wenn ich in die Dokumentation hinter »level« „read-only“ schreibe. Wenn sich dann jemand nicht daran hält, wird er schon genau wissen, was er tut, oder eben nicht, dann ist ihm aber auch nicht mehr zu helfen.
Wenn ich mich beim Setzen verschreibe kann das zu schwer auffindbaren Fehlern führen, weil das Problem nicht sofort gemeldet wird. Ein falsch geschriebener Setter meldet sich sofort mit einem AttributeError. Andererseits sollten Programmteile sowieso nicht so komplex und nicht getestet sein, dass sich ein solcher Fehler lange verstecken kann.
Fazit: auch Setter haben nicht wirklich einen Vorteil.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Das wurde doch eben von /me widerlegt…meego hat geschrieben:Dann hat sein Stabilitätsargument schon etwas.
Was wir brauchen sind Getter für Setter! Denn Getter sind ja auch nur Attribute, auf die kann man ja auch zugreifen oder sie *gasp* editieren. Da würde ich empfehlen auf Nummer sicher zu gehen und für die Setter auch Getter schreiben, ``class.get_setter('level').set(42)``. Ohnein, jetzt ist der ``get_setter`` auch ein öffentliches Attribut das man ebenfalls editieren kann, und dann gehen alle Setter kaputt! Wir brauchen einen ``class.get_setter_getter().get_setter('level').set(42)``. Verdammt, nun wiederholt sich das Problem. Vielleicht eine ``GetSetterFactory`` probieren? Wir könnten die Getter und Setter aber auch aus dem Quellcode rausnehmen und in einer XML-Datei konfigurieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Ein bißchen off-topic, aber zum Kapseln ganz wichtig:
Code: Alles auswählen
import inspect
def protected(func):
def check(self, *args,**kw):
caller=inspect.stack()[1][0]
caller_cls=type(caller.f_locals.get('self'))
assert caller_cls in self._FRIENDS, "protected method call"
return func(self, *args,**kw)
return check
class MyFriend(object):
def __init__(self, obj):
print obj.get_value()
class ILikeCpp(object):
_FRIENDS = [MyFriend]
def __init__(self, value):
self.__value = value # double __ for extra security
@protected
def get_value(self):
return self.__value
if __name__ == '__main__':
obj = ILikeCpp(23)
MyFriend(obj)
print obj.get_value() # not allowed
Dieses Kurszitat ist in dem Kontext auch nicht richtig. Technisch stimmt es zwar, hat aber nichts mit der Kapselung privater Codestellen zu tun, sondern ist als Python-Sprachmittel zur Umgehung von Namenskollisionen bei Vererbungshierarchien gedacht. Als solches sollte es auch vermittelt werden — statt dessen wird es zumeist im Zusammenhang mit "privaten" Variablen eingeführt und fälschlicherweise auch oft so verwendet.meego hat geschrieben:The mangling, however, is predictable, so it still doesn't prevent external access."
@meego: Warum? Was ist an `spam.get_parrot()` übersichtlicher als `spam.parrot`? Das kann ich nicht nachvollziehen.
Beim Aufruf gibt es wenige Unterschiede, aber innerhalb des Moduls wird ggf. klarer, welche Attribute öffentlich gedacht sind.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Normalerweise will man ja eher nicht auf eine einzelne Variable zugreiffen. Wieso also bei Einzelattributen auf andere Konzepte ausweichen? Mir kommt das etwas inkonsistent vor.BlackJack hat geschrieben:@meego: Warum? Was ist an `spam.get_parrot()` übersichtlicher als `spam.parrot`? Das kann ich nicht nachvollziehen.
@meego: Sorry, das verstehe ich nicht. Natürlich will man auch auf einzelne Variablen zugreifen. Wenn Du `spam.get_parrot()` schreibst, dann willst Du ja auf den `parrot`-Wert zugreifen. Warum soll alles was auf einem Objekt als Attribut vorhanden ist, aufrufbar sein? Zumal das ja im Gegensatz zur Standardbibliothek und den meisten Modulen von Drittanbietern inkonsistent wäre. Denn dort gibt es ja nicht nur aufrufbare Objekte als Attribute.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Gehn wir mal einen Schritt zurueck: Getter, Setter und Attributszugriffe (von aussen) sind alle aus dem gleichen Grund schlecht: Man weiss zuviel ueber andere Klassen.
Stattdessen sollte man eben Methoden aufrufen, die auf dem Zustand operieren, so wie Gott^WAlan Kay das wollte.
Warum man nicht auf eine einzelne Variable (besser: Namen) zugreifen will, ist mir allerdings ein Raetsel. Was ist denn ein Getter, wenn nicht ein umstaendlicher Attributszugriff?
Stattdessen sollte man eben Methoden aufrufen, die auf dem Zustand operieren, so wie Gott^WAlan Kay das wollte.
Warum man nicht auf eine einzelne Variable (besser: Namen) zugreifen will, ist mir allerdings ein Raetsel. Was ist denn ein Getter, wenn nicht ein umstaendlicher Attributszugriff?
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Ich find's halt übersichtlicher, wenn es explizit als Methode daherkommt.BlackJack hat geschrieben:@meego: Sorry, das verstehe ich nicht. Natürlich will man auch auf einzelne Variablen zugreifen. Wenn Du `spam.get_parrot()` schreibst, dann willst Du ja auf den `parrot`-Wert zugreifen.
Ich dachte, in Python wäre alles irgendwie als Attribut vorhanden.Warum soll alles was auf einem Objekt als Attribut vorhanden ist, aufrufbar sein?
Du magst es gewohnt sein, aber vergleiche das folgende:meego hat geschrieben:Ich find's halt übersichtlicher, wenn es explizit als Methode daherkommt.
Code: Alles auswählen
class Car(object):
color = 'red'
def get_color():
return self.color
my_car = Car()
print my_car.get_color()
# versus:
class Car(object):
color = 'red'
my_car = Car()
print my_car.color
@meego: Objekte haben Attribute, aber nicht jedes Attribut ist aufrufbar. Genau das forderst Du aber weil das übersichtlicher sein soll. Letztendlich forderst Du das es Datenattribute geben müsste, die man nicht direkt abrufen kann. Also zumindest nicht ausserhalb von Methoden auf dem Objekt.
Wie stehst Du zu der Aussage das die vielen dann nötigen trivialen Getter und Setter den Quelltext einer Klasse nur unnötig aufblähen und damit unübersichtlicher machen, weil man diesen Boilerplate-Code immer ignorieren muss, beziehungsweise genau hinschauen muss, ob die wirklich trivial sind, oder vielleicht doch etwas machen? Und innerhalb von Methoden auf der Klasse muss man sich dann immer entscheiden ob man auf das Attribut direkt zugreift, oder über die Getter/Setter.
Das hier:
ist übersichtler als das hier
?
Und wozu bietet die Sprache Properties wenn man immer Getter und Setter schreiben würde?
Wie stehst Du zu der Aussage das die vielen dann nötigen trivialen Getter und Setter den Quelltext einer Klasse nur unnötig aufblähen und damit unübersichtlicher machen, weil man diesen Boilerplate-Code immer ignorieren muss, beziehungsweise genau hinschauen muss, ob die wirklich trivial sind, oder vielleicht doch etwas machen? Und innerhalb von Methoden auf der Klasse muss man sich dann immer entscheiden ob man auf das Attribut direkt zugreift, oder über die Getter/Setter.
Das hier:
Code: Alles auswählen
class A(object):
def __init__(self):
self._spam = 42
self._parrot = 23
def get_spam(self):
return self._spam
def set_spam(self, value):
self._spam = value
def get_parrot(self):
return self._parrot
def set_parrot(self, value):
self._parrot = value
def modify(self):
self.set_parrot(self.get_parrot() * 2 + self.get_spam())
Code: Alles auswählen
class A(object):
def __init__(self):
self.spam = 42
self.parrot = 23
def modify(self):
self.parrot = self.parrot * 2 + self.spam
Und wozu bietet die Sprache Properties wenn man immer Getter und Setter schreiben würde?
BJ:
Was fordere ich jetzt? Ich sehe Scotts Punkt da schon, grosse Programme würden dadurch erheblich stabiler.Objekte haben Attribute, aber nicht jedes Attribut ist aufrufbar. Genau das forderst Du aber weil das übersichtlicher sein soll. Letztendlich forderst Du das es Datenattribute geben müsste, die man nicht direkt abrufen kann.
Codefolding?Wie stehst Du zu der Aussage das die vielen dann nötigen trivialen Getter und Setter den Quelltext einer Klasse nur unnötig aufblähen und damit unübersichtlicher machen.
Java wird auch Properties haben. Die Frage scheint mir eher, wie sehr man auf OOP setzt und ob man alleine oder in einem Team an etwas arbeitet.Und wozu bietet die Sprache Properties wenn man immer Getter und Setter schreiben würde?
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Ich sehe den Punkt dagegen nicht, warum soll denn ein Attributszugriff durch eine Methode passieren? Große Programme werden nicht durch mehr Methoden stabiler, sondern dadurch dass man Zuständigkeiten absteckt. Dazu braucht man keine Zugriffsrechte und schon gar keine Methoden, sondern allein Konventionen.meego hat geschrieben:Was fordere ich jetzt? Ich sehe Scotts Punkt da schon, grosse Programme würden dadurch erheblich stabiler.
Code der existiert muss gewartet werden.meego hat geschrieben:Codefolding?Wie stehst Du zu der Aussage das die vielen dann nötigen trivialen Getter und Setter den Quelltext einer Klasse nur unnötig aufblähen und damit unübersichtlicher machen.
[/quote]meego hat geschrieben:Java wird auch Properties haben. Die Frage scheint mir eher, wie sehr man auf OOP setzt und ob man alleine oder in einem Team an etwas arbeitet.Und wozu bietet die Sprache Properties wenn man immer Getter und Setter schreiben würde?
Java hat Properties, aber die bedeuten etwas anderes. Java hat dagegen nichts mit dem man Attributszugriffe transparent durch Funktionen bzw Funktionsaufrufe ersetzen kann.
Das Problem hat nichts mit OOP im eigentlichen Sinne zu tun, sondern ganz allgemein mit dem Arbeiten mit Abstraktionen und Schnittstellen. Man arbeitet nicht deshalb objektorientiert, weil man Getter und Setter hat.
Letztendlich muss man auf den Boden zurückkommen und einsehen: Wir arbeiten mit Python und Python hat keine Zugriffsbeschränkungen für Attribute. Wenn man dennoch darauf beharrt, arbeitet man gegen die Sprache und gegen die Community, die auf Konvention setzt.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@meego: Mir ist kein Editor bekannt der solches Code-Folding beherrscht. Und wenn man triviale Getter und Setter durch Code-Folding wieder ausblenden muss, warum muss man sie denn dann überhaupt *schreiben*. Du sagst doch durch den Boilerplate-Code wird es übersichtlicher. Wenn es übersichtlich wäre, müsste man es doch nicht ausblenden, denn es wäre ja übersichtlicher wenn es *da* ist.
Java hat keine Properties im Sinne von Python (oder C#, D, Vala). Genau *deswegen* schreibt man in Java ja auch triviale Getter und Setter. Nur deshalb ist das dort notwendig wenn man den Code mal ändern will ohne das sich die Schnittstelle nach aussen ändert.
Java hat keine Properties im Sinne von Python (oder C#, D, Vala). Genau *deswegen* schreibt man in Java ja auch triviale Getter und Setter. Nur deshalb ist das dort notwendig wenn man den Code mal ändern will ohne das sich die Schnittstelle nach aussen ändert.
Ich habe mir jetzt mal verschiedene kleinere Projekte angeschaut (Sqalchemy, django, bottle, mercurial, numpy) Keines davon benutzt Getter oder Setter.meego hat geschrieben:[…] grosse Programme würden dadurch erheblich stabiler.
[…] Die Frage scheint mir eher, wie sehr man auf OOP setzt und ob man alleine oder in einem Team an etwas arbeitet.
Im Gegenteil: vielfach wird versucht, möglichst viel wie einen Attributzugriff aussehen zu lassen, weil es die bequemste und übersichtlichste Art ist Informationen abzufragen oder zu setzen.
Weil ich es neulich in meiner Excel-Klasse hatte (nicht gerade schön aber für Datenhaltungsklassen praktisch):
Code: Alles auswählen
cell.border.left.color = cell.border.right.color = Color.red