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
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:[...]
Dein Beispiel mit den zu vielen öffentlichen Methoden habe ich nicht ganz verstanden!? Eine Klasse mit 20 getter-Methoden hat IMHO zuviele davon, nämlich genau 20 Stück. ;-)
Verstehe nicht genau was du meinst? Magst das erklären? :)

lg

Edit (Leonidas): Aus dem Thread statische Code Analyse für Python herausgetrennt.
BlackJack

Das 20 Attribute höchstwahrscheinlich "pythonischer" wären.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Also du meinst das man lieber 20 Attribute ohne get Methoden habe soll oder bzw. das es überflüssig ist für die Attribute eine Get Metzhode zu definieren? 0o

Aber gerad das ist doch der sinn in OO -> Datenkapselung -> Kein direkten zugriff auf die Attribute bzw. Kalassenvariable um vor Unsachgemäßen Falscheingaben zu schützen.

Jeder Zugriff sollte über Methode erfolgen die auch überprüfen ob richtige werte an die Parameter übergeben wurden. Es sollte nicht direkt auf die Attribute zurückgegriffen werden (schlechter Programmierstiel!!). Dabei spielt es auch kein Rolle ob es sich lediglich um eine Primitive Get Methode handelt oder um ein Set Methode.

Zumindest baut man sich so Klassen in C++ nach dieser Regel--> Attribute werden als Private definiert die mit öffentlichen Methoden angesprochen werden. Genau das ist (unter anderem) der sinn einer klasse --> Kurz gesagt: Datenkapslung ;)

Ich kann mir nicht vorstellen das Python in dieser Beziehung allen Konventionen widerspricht…
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

btw. ihr redet gerade über: http://de.wikipedia.org/wiki/Datenkapse ... mierung%29 oder auch "Geheimnisprinzip"...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

XtraNine hat geschrieben:Also du meinst das man lieber 20 Attribute ohne get Methoden habe soll oder bzw. das es überflüssig ist für die Attribute eine Get Metzhode zu definieren? 0o
Genau das.
Aber gerad das ist doch der sinn in OO -> Datenkapselung -> Kein direkten zugriff auf die Attribute bzw. Kalassenvariable um vor Unsachgemäßen Falscheingaben zu schützen.
Datenkapselung ist nicht das gleiche wie Zugriffsschutz.

Triviale getter und setter die einfach nur das Attribut setzen oder lesen, schützen auch nicht sondern sind nur unnötiger Quelltext.
Jeder Zugriff sollte über Methode erfolgen die auch überprüfen ob richtige werte an die Parameter übergeben wurden. Es sollte nicht direkt auf die Attribute zurückgegriffen werden (schlechter Programmierstiel!!). Dabei spielt es auch kein Rolle ob es sich lediglich um eine Primitive Get Methode handelt oder um ein Set Methode.
Das mit dem überprüfen ob die richtigen Argumente übergeben wurden, fällt in Python sowieso in den allermeisten Fällen weg, weil es das Duck Typing aushebelt, also eine sehr wesentliche Eigenschaft von dynamisch typisierten Programmiersprachen.

Und es spielt eine Rolle ob es nur primitive getter und setter sind. Einfach zu sagen das ist schlechter Stil reicht nicht, das musst Du auch begründen. Und die Begründung von C++ greift bei Python nicht.
Zumindest baut man sich so Klassen in C++ nach dieser Regel--> Attribute werden als Private definiert die mit öffentlichen Methoden angesprochen werden. Genau das ist (unter anderem) der sinn einer klasse --> Kurz gesagt: Datenkapslung ;)
Da wirfst Du wieder Datenkapselung und Zugriffsschutz zusammen. Datenkapselung heisst, dass man auf interne Daten nicht zugreift, auch nicht wenn man dürfte. In Python macht man interne Attribute durch einen vorangestellten Unterstrich deutlich. Das ist Datenkapselung, da braucht man nicht zwingend Mechanismen die den Zugriff auch wirklich verbieten.

Die Datenkapselung bezieht sich auch nur auf die internen Daten eines Objekts, es spricht also nichts dagegen ein Attribut als API zu erklären und somit öffentlich zugänglich zu machen. Genau das gleiche würde man mit einem trivialen getter/setter Methodenpaar auch machen, nur eben mit mehr Aufwand verbunden.
Ich kann mir nicht vorstellen das Python in dieser Beziehung allen Konventionen widerspricht
Warum nicht? Konventionen gelten immer nur in einem bestimmten Kontext und sollten durchaus hinterfragt werden können wenn sich der Kontext ändert.

In Python wird vom Programmierer erwartet, dass er weiss was er tut und verantwortlich handelt. Wenn man in den Interna eines Objekts herumpfuscht, obwohl diese als Interna gekennzeichnet sind, dann ist das ein Problem des Programmierers und nicht der Sprache die nicht restriktiv genug ist.

C++ und Java sind Sprachen, die versuchen sehr restriktiv zu sein und bei denen es eine klare Unterscheidung zwischen (Daten)Attributen und Methoden gibt.

In Python vertraut man mehr auf den Programmierer der denken und lesen kann und es gibt keine klare Grenze zwischen (Daten)Attributen und Methoden. Beides sind in Python gleichwertige Attribute und bei jedem Attributzugriff kann beliebiger Programmcode ausgeführt werden.

Selbst wenn sich also die Interna eines Objekts ändern, kann man in Python weiterhin die gleiche API nach aussen anbieten. Kleines Beispiel ein Kreis-Objekt mit Radius und Durchmesser. Da sich beide gegenseitig definieren, macht es keinen Sinn beide Werte zu speichern, also entscheidet man sich für eines und berechnet das andere bei Bedarf:

Code: Alles auswählen

class Circle(object):
    def __init__(self):
        self.radius = 10
    
    def _get_diameter(self):
        return self.radius * 2
    
    def _set_diameter(self, value):
        self.radius = value / 2

    diameter = property(_get_diameter, _set_diameter)


def main():
    circle = Circle()
    print circle.radius, circle.diameter
    circle.diameter = 100
    print circle.radius, circle.diameter
Hier liesse sich jetzt `radius` zu einem Property machen und `diameter` zu einem "einfachen" Attribut ohne das der Benutzer etwas davon in der API merken würde. So eine Möglichkeit gibt es in C++/Java nicht, darum steckt man dort vorsorglich alles in getter und setter.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Datenkapselung ist nicht das gleiche wie Zugriffsschutz.
Naja sagen wir es mal so: Die Philosophie der Objektorientierten Programmierung besteht doch (unter anderem, da gehört noch viel mehr dazu) darin, das man Wichtige Attribute (eigentlich alle nach C++/Java) dem Anwender nicht zugänglich macht und NUR Methoden zum Zugriff definiert, die auch genau überprüfen ob die übergebene Werte der Argument auch ordnungsgemäß sind (Damit meine ich nicht Datentypen wie von dir gemeint…
Das mit dem überprüfen ob die richtigen Argumente übergeben wurden, fällt in Python sowieso in den allermeisten Fällen weg, weil es das Duck Typing aushebelt,
…da reden wir gerade an einander vorbei. Es geht um die übergebenen werte ob die richtig sind.)
Da wirfst Du wieder Datenkapselung und Zugriffsschutz zusammen. Datenkapselung heisst, dass man auf interne Daten nicht zugreift, auch nicht wenn man dürfte.
Nicht wirklich ;) Datenkapselung heißt dass man die Daten vom Benutzer verbirgt und nicht zugänglich macht und nur über Spezielle Methoden darauf zurückgegriffen werden darf. Das dient (im trivialsten fall) zum Schutz vor flanschen Werteingaben. Oder ums genauer zu sagen; Es wird klar zwischen Daten (nicht zugänglich = Private) und Methoden unterschieden (öffentliche definierte Methoden = Public).

Aber die eigentliche Philosophie von OO ist das man Daten (Variablen, Attribute wie immer man das nenne will) klar trennt von den Methoden, weil ein Klasse, die in Abstrakter Form ein Objekt mit Eigenschaft darstellt. Und wir wissen ja aus der Wirklichkeit das die Eigenschaften (im OO gleich Attribute) von Realen Objekten nicht direkt manipulierbar sind sondern nur über die zu Verfügung gestellten "Methoden".

Beilspiel:
So ist es uns zum Beilspiel nicht möglich eine Information (zB. wie das Wetter heute wahr) in ein Menschliches Gehirn des Gegenübers direkt zu Pflanzen. Das kann z.B. nur über die Methode dein_Mund_sagt_etwas(self, information) zu mein_ohr_hört_zu(self, information) geschehen oder durch die Methode deine_hand_schreibt_was(self, information) zu meine_augen_lesen_das(self, information).
Bei der Methode mein_ohr_hört_zu und meine_augen_lesen_das kommen dann noch diverse weitere Faktoren (die wider durch interne Attribute, die nicht direkt manipulierbar sind, bestimmt werden) wie, __hab_ich_lust_zuzuhören, __ist_der_gegenüber_sympatischc , __fühle_ich_mich_heute_überhaupt_gut, etc xD Je nachdem wie die weiteren Faktoren ausfallen findet dann eine Informationsaufnahme statt ;) So, nach deinem Beispiel bzw. deiner Philosophie von Objektorientierter Programmierung würdest du folgendes machen:
__hab_ich_lust_zuzuhören = maxValue
__ist_der_gegenüber_sympatisch = maxValue
__fühle_ich_mich_heute_überhaupt_gut = maxValue


__Gehirn.append ("Schönes wettert heute wa?")
startDenkprozessEinleiten(...)
;) Ich hoffe ich konnte dir näher bringen worauf ich hinaus wollte bei meinen vorigen Post zu Thema OO und Klassendesign.
Und es spielt eine Rolle ob es nur primitive getter und setter sind. Einfach zu sagen das ist schlechter Stil reicht nicht, das musst Du auch begründen. Und die Begründung von C++ greift bei Python nicht.
Eine Saubere Klasse in C++ ist ein Klasse die keinerlei zugriff auf Variabeln (Attribute) zulässt sondern nur den Zugriff über Methoden zulässt. Alles andere ist sehr schlechter Programmierstiel, was ich ja eben oben begründet habe aus der Sicht der eigentlichen Philosophie der Objektorientierten Programmierung.

Hier liesse sich jetzt `radius` zu einem Property machen und `diameter` zu einem "einfachen" Attribut ohne das der Benutzer etwas davon in der API merken würde. So eine Möglichkeit gibt es in C++/Java nicht, darum steckt man dort vorsorglich alles in getter und setter.
Oh O.K... Zugegeben ein wirklich sehr, sehr schönes Design. Ich wuste gar nicht das dass möglich ist. Danke für deine Erklärung :) Python wird mir immer Sympathischer!! :)

lg
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

[schlechter wortwitz]Ich geh mir jetzt ein Eis am Stil kaufen und dann les ich mir den Thread nochmal durch[/schlechter wortwitz]
TUFKAB – the user formerly known as blackbird
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Ja mach das! :lol:
BlackJack

XtraNine hat geschrieben:
Datenkapselung ist nicht das gleiche wie Zugriffsschutz.
Naja sagen wir es mal so: Die Philosophie der Objektorientierten Programmierung besteht doch (unter anderem, da gehört noch viel mehr dazu) darin, das man Wichtige Attribute (eigentlich alle nach C++/Java) dem Anwender nicht zugänglich macht und NUR Methoden zum Zugriff definiert,
Und wenn man Methoden zum Zugriff definiert, dann macht man die Attribute doch wieder zugänglich. Dem Anwender wirklich wichtige Attribute nicht zugänglich zu machen wäre komisch, weil sie ja offensichtlich wichtig sind.

Das ist eher die Philosophie von C++ und Java alle Attribute privat zu deklarieren und nicht universell auf OOP übertragbar. Und das ist in C++ und Java so weil dort im Objektmodell eine Unterscheidung zwischen Attributen und Methoden gemacht wird. Das ist in Python nicht der Fall. Dort sind einerseits alles Attribute und andererseits kann bei jedem Attributzugriff vordefinierter Code ausgeführt werden.
die auch genau überprüfen ob die übergebene Werte der Argument auch ordnungsgemäß sind (Damit meine ich nicht Datentypen wie von dir gemeint…
Das mit dem überprüfen ob die richtigen Argumente übergeben wurden, fällt in Python sowieso in den allermeisten Fällen weg, weil es das Duck Typing aushebelt,
…da reden wir gerade an einander vorbei. Es geht um die übergebenen werte ob die richtig sind.)
Aber Werte sind in Python hauptsächlich "Verhalten". Wie willst Du das prüfen ohne letztendlich das übergebene Objekt so zu benutzen wie es später einmal verwendet werden soll!? Das geht nicht wirklich. Insbesondere bei Objekten deren Zustand sich durch das Benutzen verändert.
Da wirfst Du wieder Datenkapselung und Zugriffsschutz zusammen. Datenkapselung heisst, dass man auf interne Daten nicht zugreift, auch nicht wenn man dürfte.
Nicht wirklich ;) Datenkapselung heißt dass man die Daten vom Benutzer verbirgt und nicht zugänglich macht und nur über Spezielle Methoden darauf zurückgegriffen werden darf.


Nein, das ist Zugriffschutz. Wenn ich in C `struct`s erstelle und diese nur mit dazugehörigen Funktionen bearbeite und nicht direkt darin herumpfusche, dann betreibe ich auch Datenkapselung.

Wenn Datenkapselung zwingend Zugriffsschutz voraussetzen würde und OOP ohne Datenkapselung nicht geht, dann wäre in Python kein OOP möglich. Es ist aber sogar in C machbar, wenn auch etwas umständlich, weil die Sprache keine spezielle Unterstützung dafür anbietet.
Das dient (im trivialsten fall) zum Schutz vor flanschen Werteingaben. Oder ums genauer zu sagen; Es wird klar zwischen Daten (nicht zugänglich = Private) und Methoden unterschieden (öffentliche definierte Methoden = Public).
Wenn ich ein privates Attribut habe für das es einen öffentlichen Getter/Setter gibt, dann ist dieses Attribut de facto öffentlich. Damit ist die Unterscheidung überflüssig.
Aber die eigentliche Philosophie von OO ist das man Daten (Variablen, Attribute wie immer man das nenne will) klar trennt von den Methoden, weil ein Klasse, die in Abstrakter Form ein Objekt mit Eigenschaft darstellt.
Die eigentliche OO Philosophie spricht nicht von Daten und Methoden sondern von Objekten und Nachrichten. Man schickt einem Objekt eine Nachricht und bekommt ein Objekt als Antwort. Im Fall vom Kreis schicke ich einem Kreis-Objekt die Nachricht `radius` und bekomme ein Objekt zurück, welches sich wie eine Zahl verhält. Ob ich direkt ein fertiges Objekt aus dem Namensraum des Objektes bekomme oder etwas, das erst berechnet werden muss, entscheidet das Kreis-Objekt! Jedenfalls ist das in Python so. In C++ und Java gibt es die klare Unterscheidung zwischen Daten (Attribute) und Code (Methoden), das ist aber nicht gottgegeben und von OO so vorgeschrieben.

`radius` ist eine Eigenschaft von Kreisen und zwar eine die von öffentlichem Interesse ist.
Und wir wissen ja aus der Wirklichkeit das die Eigenschaften (im OO gleich Attribute) von Realen Objekten nicht direkt manipulierbar sind sondern nur über die zu Verfügung gestellten "Methoden".
Reale Objekte haben keine Methoden. Das scheinst Du zumindest unbewusst schon selbst so zu sehen, sonst hättest Du es nicht in Anführungszeichen gesetzt.
Beilspiel:
So ist es uns zum Beilspiel nicht möglich eine Information (zB. wie das Wetter heute wahr) in ein Menschliches Gehirn des Gegenübers direkt zu Pflanzen. Das kann z.B. nur über die Methode dein_Mund_sagt_etwas(self, information) zu mein_ohr_hört_zu(self, information) geschehen oder durch die Methode deine_hand_schreibt_was(self, information) zu meine_augen_lesen_das(self, information).
Bei der Methode mein_ohr_hört_zu und meine_augen_lesen_das kommen dann noch diverse weitere Faktoren (die wider durch interne Attribute, die nicht direkt manipulierbar sind, bestimmt werden) wie, __hab_ich_lust_zuzuhören, __ist_der_gegenüber_sympatischc , __fühle_ich_mich_heute_überhaupt_gut, etc xD Je nachdem wie die weiteren Faktoren ausfallen findet dann eine Informationsaufnahme statt ;) So, nach deinem Beispiel bzw. deiner Philosophie von Objektorientierter Programmierung würdest du folgendes machen:
__hab_ich_lust_zuzuhören = maxValue
__ist_der_gegenüber_sympatisch = maxValue
__fühle_ich_mich_heute_überhaupt_gut = maxValue


__Gehirn.append ("Schönes wettert heute wa?")
startDenkprozessEinleiten(...)
;) Ich hoffe ich konnte dir näher bringen worauf ich hinaus wollte bei meinen vorigen Post zu Thema OO und Klassendesign.
Nicht wirklich, weil Programmieren immer eine Abstraktion der Realität darstellt und der Programmierer bestimmen kann wo die Grenzen liegen.

Du hast auch eine Menge in Deinem Pseudocode weggelassen. Ich nehme an es geht um Attribute eines `Gehirn` Objektes. Dann würde man natürlich auch nach "meiner" Sicht von OOP Datenkapselung betreiben. Also Attribute die einen führenden Unterstrich haben, würde man von aussen nicht benutzen. Ausnahme: Man wüsste genau was man tut weil man die Interna kennt. Objekte vom Typ `Gehirnchirurg`, `Seelenklempter` und `Hypnotiseur` kämen da in Frage. (In C++ wären das `friend`s.)
Und es spielt eine Rolle ob es nur primitive getter und setter sind. Einfach zu sagen das ist schlechter Stil reicht nicht, das musst Du auch begründen. Und die Begründung von C++ greift bei Python nicht.
Eine Saubere Klasse in C++ ist ein Klasse die keinerlei zugriff auf Variabeln (Attribute) zulässt sondern nur den Zugriff über Methoden zulässt. Alles andere ist sehr schlechter Programmierstiel, was ich ja eben oben begründet habe aus der Sicht der eigentlichen Philosophie der Objektorientierten Programmierung.
Du hast es nicht wirklich begründet. Du hast nicht die Frage nach dem warum beantwortet, sondern nur genauso dogmatisch gesagt man trennt in OO in private Attribute und öffentliche Methoden ein. Das ist in C++ so, aber nicht in Python. Oder jeder anderen Programmiersprache die das Objekt/Nachricht basierte Objektmodell implementieren. Es geht darum die interne Arbeitsweise eines Objekts für den Benutzer transparent zu machen. Das ist das warum. Und das können C++ und und Java bei öffentlichen Datenattributen nicht leisten.

Wenn Du in C++ folgenden Code hast

Code: Alles auswählen

bar = foo->baz;
dann weisst Du ganz genau, dass direkt in den Speicher gegriffen wird um das `baz` Objekt aus dem `foo` Namensraum zu holen. Es ist also unmöglich das `baz` dynamisch aus anderen Werten berechnet wird. Wenn das zukünftig irgendwann einmal der Fall sein soll, dann ändert sich für den Benutzer die API von dem Objekt weil man dann eine Methode daraus machen muss.

Und genau aus dem Grund macht man in C++ alles private, weil das die einzige Möglichkeit ist, die Implementierung transparent zu machen.

Du kannst aber unmöglich sagen was in Python bei

Code: Alles auswählen

bar = foo.baz
passiert, ohne in den Quelltext zu schauen. Das ist absolut das Betriebsgeheimnis des `foo` Objekts. Es kann sein, das ein Objekt aus dem Namensraum geholt wird. Oder das im Namensraum ein Objekt unter dem Namen liegt, welches das Deskriptor-Protokoll implementiert und das Ergebnis erst von diesem Objekt erzeugt wird (Beispiel: property) oder das es so ein Objekt im Namensraum gar nicht gibt und die `__getattr__()` Methode ausgeführt wird. Also alles was bei `get_baz()` auch gemacht werden könnte.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hey danke dir BlackJack das du dir die mühe gemacht hast darauf einzugehen :) Du hast es gut beschrieben wo die unterschiede liegen bei OOP zwischen C++ und Pyhon. Ich merke gerade dass ich in der Beziehung umdenken muss/werde. Ich werde mir auch angewöhnen Triviale Gatter und Setter (in dem fall wo wirklich nur ein wert übergeben wird ohne weitere Berechnung) zu vermeiden.

Hätte da ein frage zu property: Ist die Möglichkeit immer angebracht oder sollte man damit eher sparsam umgehen? Was ich nicht so recht verstehe ist woher Python genau weise welche Methode zu dem Diameter aufgerufen werden soll (wahrscheinlich weil Python dan merkt das _set_diamater ein Argument erwartet oder?)? Und wie sieht es aus wenn man z.B. verschiedene _set_diameter Methoden definiert? Woher weis Python welche die richtige ist? Bzw. sind damit auch Überladungen von Methoden realisierbar?

Dan ne andere Frage: Interne Attribute/Methoden werden immer mit einen unterstrich am Anfang definiert. Ich mache das aber immer mit 2 unterstrichen am Anfang. Ist das OK oder wäre das eher ein schlechter Stiel?

lg
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

XtraNine hat geschrieben:Stiel?
Nein. Stil!!! Und das hab ich mit meinem schlechten Wortwitz schon versucht anzudeuten... :roll:

Properties verwendest du nur wenn du sie brauchst. Ansonsten schreibst du direkt die Attribute auf die Klasse. Und welche Methode er aufruft? Die, die du übergibst.
TUFKAB – the user formerly known as blackbird
BlackJack

XtraNine hat geschrieben:Dan ne andere Frage: Interne Attribute/Methoden werden immer mit einen unterstrich am Anfang definiert. Ich mache das aber immer mit 2 unterstrichen am Anfang. Ist das OK oder wäre das eher ein schlechter Stiel
Bei zwei Unterstrichen wird der Name "verstümmelt", dass heisst man kann so direkt nur innerhalb der Methoden der Klasse auf diese Attribute zugreifen. Also zum Beispiel nicht von Methoden einer Unterklasse aus. Dieser Mechanismus ist hauptsächlich dazu gedacht um Namenskollisionen bei Unterklassen und noch wichtiger bei Mix-Ins zu vermeiden.

Das ist aber kein Schutz im Sinne von ``private`` in C++ oder Java weil der Mechanismus der Namensverstümmelung bekannt ist. Es wird ein Unterstrich und der Klassenname vor den Namen gesetzt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

blackbird hat geschrieben:
XtraNine hat geschrieben:Stiel?
Nein. Stil!!! Und das hab ich mit meinem schlechten Wortwitz schon versucht anzudeuten... :roll:
Ist ja gut. Na und?! nun hab ich schon zum dritten mal den Fehler gemacht Stil mit e zu schreiben. Machst du keine Fehler? Nobody is Perfect…:roll:
blackbird hat geschrieben:[
Properties verwendest du nur wenn du sie brauchst. Ansonsten schreibst du direkt die Attribute auf die Klasse. Und welche Methode er aufruft? Die, die du übergibst.
Geht es noch untransparenter? Hauptsache du hast dein Spaß dran dich über meine Orthografischen Leistungen, in form von Multiplen Satzeichen (--> !!!) und rollenden Augen, aufzuregen…Schwach, sehr schwach und das von einem Admin bzw. Mod Bild

Also noch mal um das zu konkretisieren: Was heißt "Properties verwendest du nur wenn du sie brauchst" ? -->Wann braucht man das und wann nicht?
Ist ein Übereinsatz ein Schlechter Stil oder ist das egal?

"Und welche Methode er aufruft? Die, die du übergibst" Ja ne ist klar (Sorry jetzt muss ich mit den Augen rollen). :roll: Begründung = Siehe oben (!=Tranzparent)...

-------------------------------------------------------------------------------------

@BlackJack: Danke dir für die Antwort :) 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)?
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"
LG XtraNine
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

XtraNine hat geschrieben:Geht es noch untransparenter? Hauptsache du hast dein Spaß dran dich über meine Orthografischen Leistungen, in form von Multiplen Satzeichen (--> !!!) und rollenden Augen, aufzuregen…Schwach, sehr schwach und das von einem Admin bzw. Mod Bild
Ein Admin bzw. Moderator im Forum zu sein, heißt nicht, dass man immer gut gelaunt sein muss.

Hier hast du mal ein Beispiel aus der Doku für Properties:

Code: Alles auswählen

class C(object):
    def get_size (self):
        result = ... computation ...
        return result
    def set_size (self, size):
        ... compute something based on the size
        and set internal state appropriately ...

    # Define a property.  The 'delete this attribute'
    # method is defined as None, so the attribute
    # can't be deleted.
    size = property(get_size, set_size,
                    None,
                    "Storage size of this instance")
XtraNine hat geschrieben:Also noch mal um das zu konkretisieren: Was heißt "Properties verwendest du nur wenn du sie brauchst" ? -->Wann braucht man das und wann nicht?
Ist ein Übereinsatz ein Schlechter Stil oder ist das egal?
Ich würde sagen es ist schlechter Stil, properties einzusetzen "nur weil man es kann". Sagen wir mal du hast ein Objekt, den Kreis. Dieser Kreis hat einen Radius. Der Radius kann aber maximal 10 sein. Dann kann es sinnvoll sein, ein write-Property zu machen, dann im Falle wenn jemand 11 einsetzt eine passende Exception wirft. Aber generell ist sowas meist nicht nötig.
XtraNine hat geschrieben:"Und welche Methode er aufruft? Die, die du übergibst" Ja ne ist klar (Sorry jetzt muss ich mit den Augen rollen). :roll: Begründung = Siehe oben (!=Tranzparent)...
Wenn du dir ansiehst, wie man ein Property definiert, dann markst du dass die Frage sinnlos ist, weil es sofort ersichtlich ist, welche Methode aufgerufen wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

O.K. danke dir. Dann werde ich Properties nur benutzen wenn es wirklich erforderlich ist bzw. ganz drauf verzichten.

lg
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