Properties und Getters

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 08:50

BlackJack hat geschrieben:IMHO: Das Buch ist Müll. Ich habe mit dem OOP Kapitel angefangen und da wird gleich `__del__()` als Destruktor vorgestellt, ohne jegliche Warnung warum man das nicht benutzen sollte, und "private members" mit doppelten führenden Unterstrichen um "private" Daten vor Zugriff zu schützen und sinnlose, triviale Getter und Setter per `property()` um dann darauf zuzugreifen. Argh!
Das wollte ich noch fragen. Was ist an Settern und Gettern und private members so schlecht?

Edit (Leonidas): Von "Python - Das umfassende Handbuch" abgetrennt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Mittwoch 27. Februar 2008, 09:40

burli hat geschrieben:Das wollte ich noch fragen. Was ist an Settern und Gettern und private members so schlecht?
Hallo burli!

In wenigen Worten: Sie sind meist unnötig.

Man kann einer Klasseninstanz Attribute zuweisen und diese zur Laufzeit ändern. Das funktioniert alles ohne Getter und Setter.

Getter, Setter und Properties sind nur dann nötig, wenn ich beim Abfragen oder Zuweisen einer Eigenschaft etwas ausführen möchte. Und so lange das nicht der Fall ist, kann ich das durch direktes Zuweisen eines Attributes erledigen.

Ein Python-Modul ist keine Blackbox. Den Code einer Klasse kann man anschauen. Das läuft ein wenig anders als bei C++ oder Java. Es gibt keinen Grund dafür, eine Klasseninstanz vor dem Programmierer abzuschotten.

Und für einen Python-Programmierer genügt ein Unterstrich um zu erkennen, dass ein Attribut nur intern verwendet werden soll. Aber auch bei einem Unterstrich kann der Python-Programmierer selber entscheiden, ob er das Attribut trotzdem verwendet.

Und wenn der Python-Programmierer glaubt, jemanden vor einem schlimmen Fehler bewahren zu müssen, dann kann man ein Attribut mit zwei Unterstrichen kennzeichnen. Das ist dann das Zeichen "Finger weg! Du weißt nicht was du tust!". Mit zwei Unterstichen wird dann auch das zufällige Überschreiben des Attributs verhindert, da sich der Name nach außen ändert.

Leider gibt es immer wieder Programmierer, die Unterstriche unnötig excessiv einsetzen. Man sollte diese Mittel sparsam anwenden.

mfg
Gerold
:-)
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 27. Februar 2008, 09:41

burli hat geschrieben:Das wollte ich noch fragen. Was ist an Settern und Gettern und private members so schlecht?
Weil du Getter und Setter nicht drauchst, da es in Python Properties gibt, die Getter und Setter alt aussehen lassen.

Warum gibt es in Java triviale Getter und Setter? Weil es möglich ist, dass man in Zukunft die Funktionen etwas nicht triviales berechnen lassen muss, statt einfach nur Werte zu speichern oder zu setzen. In Java will man die API nicht berechen, daher verwendet man im vorhinein Getter und Setter. In Python kann man die Attribute mit Properties wrappen, da werden Getter und Setter bei Bedarf aufgerufen, ohne dass man als Nutzer der API davon was mitbekommt. Schau dir mal die Properties-Beispiele an.

In Python gibt es keine Private Members und __ sagt auch nicht das die Variable private ist. Das ist Name Mangling und nur dazu da Namenskollisionen zu verhindern. Wenn man dem Programmierer signalisieren will, dass er ein Attribut nicht anfassen will, außer er will Breakage riskieren dann nutzt man _. Aber das ist nur Konvention.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 27. Februar 2008, 11:37

Um es an einem Beispiel zu zeigen:

Code: Alles auswählen

class JavaStyle(object):
    def __init__(self, spam, ham, eggs):
        self._spam = spam
        self._ham = ham
        self._eggs = eggs
    
    def get_spam(self):
        return self._spam
    
    def set_spam(self, value):
        self._spam = value
    
    def get_ham(self):
        return self._ham
    
    def set_ham(self, value):
        self._ham = value
    
    def get_eggs(self):
        return self._eggs
    
    def set_eggs(self, value):
        self._eggs = value


class PythonStyle(object):
    def __init__(self, spam, ham, eggs):
        self.spam = spam
        self.ham = ham
        self.eggs = eggs
Wenn es für ein Attribut [GS]etter gibt, ist es letztendlich doch Teil der öffentlichen API, und man kann es auch *direkt* ansprechen. Der Quelltext wird dadurch kürzer und einfacher, weil man sich eine Menge "boilerplate" Quelltext spart, der in den meisten Fällen einfach nur eine unnötige Indirektion darstellt. Sollte man so eine Indirektion später doch einmal brauchen, gibt's `property()`. Diese Möglichkeit bietet Java nicht, darum lässt man sich dort von der IDE eben viel unnützen Code erstellen, den der Compiler dann am Ende wieder wegoptimieren darf. :-)
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 12:01

Dein Beispiel ergibt keinen Sinn, das ist klar. Die Setter/Getter sind ja in erster Linie dazu gedacht um zb zusätzliche Sicherheiten einzubauen. Zb das wirklich nur Integer von 0-100 geschrieben werden können.

Und das man dafür property() verwenden sollte war mir eigentlich schon klar, auch wenn es in dem Buch erstmal so wie in deinem Beispiel stand. Ok, vielleicht bin ich auch vorbelastet weil ich Propertys schon von anderen Sprachen kenne.

Warum Python allerdings kein richtiges private/public unterstützt hab ich noch nicht verstanden. Das mit den Unterstrichen ist ja bestenfalls ein Notbehelf.

Jedenfalls hätte ich nach dem Lesen des Buches "schützenswerte" Variablen mit einem Unterstrich versehen, Setter/Getter dafür geschrieben und ein Property angelegt. Korrigiert mich bitte wenn ich damit falsch liege
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Mittwoch 27. Februar 2008, 12:09

Hallo burli!
burli hat geschrieben:um zb zusätzliche Sicherheiten einzubauen. Zb das wirklich nur Integer von 0-100 geschrieben werden können.
Das ist ein guter Grund für ein Property und für einen Unterstrich im Attributnamen. Idealerweise kannst du den Wert bereits beim Eingeben in eine GUI überprüfen. Zustände die nie möglich sein dürften, kannst du zwischendurch auch mit ``assert`` checken.
burli hat geschrieben:Warum Python allerdings kein richtiges private/public unterstützt hab ich noch nicht verstanden. Das mit den Unterstrichen ist ja bestenfalls ein Notbehelf.
Vor wem willst du den Code schützen? Einem Programmierer könnte man doch wirklich zumuten, dass er ein Attribut, das mit Unterstrich beginnt, nur dann angreift wenn er weiß was er tut.

Willst du wirklich einen Fehler auslösen lassen, nur weil ein Programmierer weiß was der tut und das "private" Attribut trotzdem angreift? Unsinnig! Willst du statt dem Unterstrich wirklich Getter und Setter schreiben? Gut, kannst du machen.

mfg
Gerold
:-)
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Mittwoch 27. Februar 2008, 12:25

In einem Perl-Buch habe ich zu dem "fehlenden" `private` einen netten Vergleich gelesen, der ungefähr so ging (Sorry, aus dem Gedächtnis): Fremde Objekte sind wie fremde Häuser. Wir gehen da nicht rein weil es unhöflich ist, und nicht weil der Besitzer einen Elektrozaun und eine Schrotflinte hat. Möchten sie in einer Nachbarschaft wohnen, in der so etwas üblich ist!?

Wenn ein Programmierer den Hinweis "das ist ein Implementierungsdetail" nur ernst nimmt, wenn es ihm die Sprache hart verbietet auf das Attribut zuzugreifen, ist das in den Augen von den meisten Pythonistas ein ernsthaftes Problem des Programmierers und nicht der Sprache. In sofern sehen wir den Unterstrich auch nicht als "Notbehelf", weil es keine Notlage gibt. Jedenfalls nicht mit der Sprache. ;-)

Andererseits gibt es halt auch immer mal wieder Fälle, wo ein Programmierer die Interna kennt und bewusst auf sie zugreift. Im Nachbarschaftsbeispiel wäre das jemand, der netterweise den Pool des Nachbarn abdeckt, bevor er seine Hecke stutzt, damit keine Blätter in den Pool geweht werden können. In einigen Sprachen nennt man so etwas `friend`. :-)
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 12:25

Ich weiß das es im Prinzip unsinnig ist, sofern sich alle an die Regeln halten. Aber das kann keiner kontrollieren. Ganz besonders unsinnig ist es wenn den Code außer mir keiner in die Hände bekommt.

Aber völlig unsinnig sind property(Setter,Getter) auch nicht. Es geht ja nicht nur darum das der Programmierer weiß was er tut. Man kann damit ja auch Fehleingaben von Usern abfangen. Beispiel SQL Injection. Ein Setter könnte ein guter Platz sein um die ankommenden Daten auf unerwünschte Inhalte zu prüfen. Nur mal so als hypotetisches Beispiel. Ob das letztendlich sinnig ist hängt auch von der Applikation ab

Und private/protectet ist auch nicht falsch. Speziell wenn ein Programmierer die Doku nicht genau ließt und zb mit Autocomplete arbeitet. Dann sieht er alle Attribute aufgelistet, findet eins mit passendem Namen, und erwischt damit eins das er besser nicht anfassen sollte.

Auch beim Programmieren gilt: "expect the unexpected"
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 12:30

@ BlackJack: schöner Vergleich ;)

Es ist ja schön wenn Programmieren auf Vertrauensbasis funktioniert, aber garantieren kann das keiner. Manchmal vertraue ich mir ja selber nicht ;)
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Mittwoch 27. Februar 2008, 12:32

burli hat geschrieben:@ BlackJack: schöner Vergleich ;)

Es ist ja schön wenn Programmieren auf Vertrauensbasis funktioniert, aber garantieren kann das keiner. Manchmal vertraue ich mir ja selber nicht ;)
Nagut, dann baut halt jemand Mist. Er überschreibt's oder benutzt es, obwohl er es nicht sollte. Seine eigene Schuld oO' Jeder muss selber wissen, ob er in das Haus gehen möchte. Wenn er dann erschlagen wird vom Nachbarn, is's das auch.
BlackJack

Mittwoch 27. Februar 2008, 12:44

@burli: Garantieren kann das auch keiner mit `private` & Co. Jemand der die Doku nicht liest, darf sich nicht beschweren, wenn etwas nicht so funktioniert, wie er sich das denkt.

Ich tendiere dazu "read only"-Attribute als solche nur zu dokumentieren und Sachen wie "Attribut `percent` must be a number between 0 and 100" ebenfalls. Wer da unbedingt 'ne Million oder was negatives zuweisen muss, fällt halt auf die Nase. Wenn mir das selbst mal passiert, schreibe ich meistens an der Stelle wo's anfing falsch zu laufen ein ``assert`` in den Quelltext.

Testen von Benutzereingaben sollte so früh wie möglich nach der Eingabe passieren, möglichst bevor die Daten in Objekte kommen, mit denen die Programmlogik implementiert ist.

Wie Du schon sagtest: "expect the unexpected", dass muss man halt machen, wenn man ohne von einem Elektrozaun aufgehalten zu werden, in einen Sumpf spazieren kann, um den lustigen Irrlichtern zu folgen. ;-)
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 13:08

BlackJack hat geschrieben:@burli: Garantieren kann das auch keiner mit `private` & Co.
Naja, kann man schon. Ich kenn es halt von anderen Sprachen wo man auch schonmal compilierte Module bekommt und nur die Schnittstelle kennt. Es kann ja durchaus sein das in dem Modul Daten verwaltet werden die keinen was angehen. Da nutzt es nichts wenn man in die Doku schreibt: Finger weg von dem Attribut. Ich würde das mal einen entscheidenden Sicherheitsaspekt nennen. (Meinem Nachbarn würde ich auch nicht die Zahlenkombination von meinem Tresor nennen in dem vertrauliche Unterlagen liegen ;) )

In Verbindung mit Python wird das ganze natürlich etwas schwammig weil es in dem Sinn keinen sicheren Code gibt. Es ist ja problemlos möglich den Bytecode zu decompilieren. Ich denke es wird keiner so dumm sein und Module in Python schreiben die irgendwie wichtig sind.

Wie auch immer, da wo es mir sinnvoll erscheint werde ich mit Properties arbeiten und Unterstriche vor Methoden und Variablen machen, auch wenn's nur eine Gedächtnisstütze ist
BlackJack

Mittwoch 27. Februar 2008, 13:32

Also `private` in C++ kann man oft mit einer einfachen Deklaration vor dem importieren der Header-Datei weg bekommen: ``#define private public``. Falls das Layout von den beiden vom Compiler unterschiedlich behandelt werden sollte, kommt man via Typecast nach `*void` an die "geschützten" Daten.

In Java kann man über die Reflection-API an private Attribute und Methoden kommen.

Unter Sicherheitsaspekten sind das also keine allzu grossen Hürden für jemanden der da *wirklich* rankommen will oder muss.

Decompilieren und mit einem Debugger schrittweise verfolgen, geht auch in beiden Sprachen.

Und es gibt eine Menge Leute die Python-Module schreiben, die irgendwie wichtig sind. Wenn sie wichtig im Sinne von "darf keiner reinschauen" sind, dann darf man sie halt nicht aus der Hand geben. Wie bei eigentlich jedem Code der so wichtig ist. Das es für jedes auch nur halbwegs interessante "native binary"-Programm einen Crack oder Schlüsselgenerator gibt, beweist, dass keine Sprache gegen so etwas schützt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Mittwoch 27. Februar 2008, 13:40

burli hat geschrieben:da wo es mir sinnvoll erscheint werde ich mit Properties arbeiten und Unterstriche vor Methoden und Variablen machen, auch wenn's nur eine Gedächtnisstütze ist
Hallo burli!

Du wirst sehen, dass die Unterstriche komplett ausreichen.

Und ja, ich schreibe wichtige Module mit Python. Gerade deshalb!

mfg
Gerold
:-)
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 27. Februar 2008, 13:53

Das Schutzmaßnahmen ausgehebelt werden können ist bekannt. Erst kürzlich habe ich gesehen das man sogar relativ einfach an die Daten verschlüsselter Festplatten kommt.

Aber man muss sie auch nicht gleich auf dem Präsentierteller anbieten

Edit: Um bei dem Vergleich mit dem Haus zu bleiben. Du klebst deine TAN Liste ja auch nicht in's Fenster (public) sondern die liegt in einer Schublade (private). Aber einbrechen und die Liste klauen kann trotzdem jemand.
Antworten