unveränderbares Klassenattribut erstellen

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
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

pillmuncher hat geschrieben:Ich empfehle dazu dieses Buch. Es setzt zwar Grundkenntnisse in Java voraus., aber die sind an einem Wochenende leicht soweit erlernbar, dass man damit das Buch durcharbeiten kann.
Ich habe Grundkenntnisse (keine Programmiererfahrung) in Java, und das von dir empfohlene Buch habe ich vor einigen Jahren überflogen. Ich habe es dann beiseitegelassen, weil viele Konzepte, auf welche das Buches großen Wert legt, in Python nicht realisierbar sind, insbesondere :mrgreen: Kapselung und Interfaces :mrgreen: . Ja ich würde ohne Übertreibung sagen, dass meine von euch so empfundene "Python-feindliche" Einstellung ihren Ursprung in *genau diesem Buch* hat, vorher war ich da (als ehemaliger Fortran-Programmierer) viel lockerer. Deshalb wundert es mich echt, dass dieses Buch von einem Python-Anhänger empfohlen wird.
Zuletzt geändert von Goswin am Mittwoch 20. Februar 2013, 15:57, insgesamt 1-mal geändert.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Goswin: Die zentralen Konzepte des Buchs sind leicht auf Python übertragbar. Hier ein Beispiel für das Observer-Pattern in Python (das erste Pattern im Buch ist auch das Observer-Pattern):

Code: Alles auswählen

class FooBarObservable:

    def __init__(self):
        self._observers = set()
        self._foo = 0
        self._bar = 0

    def register(self, observer):
        self._observers.add(observer)

    def remove(self, observer):
        self._observers.remove(observer)

    @property
    def foo(self):
        return self._foo

    @foo.setter
    def foo(self, value):
        self._foo = value
        for each in self._observers:
            each.foo_changed(self)

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        self._bar = value
        for each in self._observers:
            each.bar_changed(self)


class FooBarObserver:

    def __init__(self, identity):
        self._identity = identity

    def foo_changed(self, observable):
        print('Observer {}: observed foo value changed to {}'.format(
            self._identity, observable.foo))

    def bar_changed(self, observable):
        print('Observer {}: observed bar value changed to {}'.format(
            self._identity, observable.bar))


server = FooBarObservable()

client1 = FooBarObserver(1)
client2 = FooBarObserver(2)
client3 = FooBarObserver(3)


server.register(client1)
server.register(client2)
server.register(client3)

server.foo = 3
server.remove(client2)
server.bar = 4
Ergebnis:

Code: Alles auswählen

Observer 1: observed foo value changed to 3
Observer 2: observed foo value changed to 3
Observer 3: observed foo value changed to 3
Observer 1: observed bar value changed to 4
Observer 3: observed bar value changed to 4
Die weiteren Patterns im Buch kann man analog dazu programmieren.

Wie man sieht, gibt es auch in Python Interfaces und Kapselung, nur gibt es diese eben nicht als explizite Konstrukte der Sprache, sondern als reine Konventionen. Ein Objekt implementiert ein Interface, sofern es bestimmte Attribute und Methoden mit bestimmten Namen und Signaturen besitzt. Das nennt man Duck Typing. Und wenn man signalisieren möchte, dass ein Attribut privat ist und von außen nicht geändert werden sollte, versieht man dessen Namen - per Konvention - mit einem führenden Unterstrich. Der Benutzer der Klasse kann dann selbst entscheiden, ob er das Risiko eingeht, etwas kaputt zu machen, indem er dieses Attribut setzt. Guido sagt dazu immer "We are all consenting adults".
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

An der Stelle merke ich immer gerne an, das Kapselung nicht das gleiche ist wie erzwungene Zugriffseinschränkungen. Kapselung heisst, dass man eine Schnittstelle anbietet und diese verwendet, und nicht zwingend, dass man Zugriff auf interna um jeden Preis verhindert. Wenn man Attribute als Interna oder nur lesend zu Verwenden kennzeichnet, dann hat man Kapselung betrieben. Wenn die jemand, inklusive man selber, diese Kapselung ohne guten Grund durchbricht, dann ist das IMHO ein Problem des Programmierers der wissentlich und willentlich Grenzen überschreitet, und keines der Programmiersprache.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

@pillmuncher:
pillmuncher hat geschrieben: Wenn man signalisieren möchte, dass ein Attribut privat ist und von außen nicht geändert werden sollte, versieht man dessen Namen - per Konvention - mit einem führenden Unterstrich.
Das weiß ich nicht nur, sondern habe es in allen meinen Programmen auch so gemacht, seitdem ich Python verwende, was jetzt einige Jahre her ist. Alles Gegenteilige sind Gedankenkonstrukte (aka "Hirngespinste") von einigen Mitgliedern in diesem Forum. Wenn ich Schwierigkeiten habe (und die habe ich öfters), meine Python-Programme zum Laufen zu bringen oder zu verwalten, hat das *absolut gar nichts* damit zu tun.

Aber last not least: Danke für deine Beispiele.
BlackJack

@Goswin: Da Du Dich gegen alle anderen Namenskonventionen so vehement sträubst, kommt einem vielleicht nicht in den Sinn, dass Du Dich an Diese hältst. ;-)
Antworten