Sollte man hier schon das Observer-Pattern verwenden...?

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

wie würdet ihr vorgehen?

So...

Code: Alles auswählen

class Timeframe(object):
    def __init__(self, years, months, days):
        self.years = years
        self.months = months
        self.days = days

class Picker(object):
    def __init__(self):
        self.picked = []

    def pick(self, item):
        do_it = self.picked.remove if \
            item in self.picked else self.picked.append
        do_it(item)

    def __iter__(self):
        for item in self.picked:
            yield item

    def __len__(self):
        return len(self.picked)

Code: Alles auswählen

>>> y = Picker()
>>> m = Picker()
>>> d = Picker()
>>> t = Timeframe(y, m, d)
>>> y.pick(2011)
>>> t.years
[2011]
... oder so ...

Code: Alles auswählen

class Timeframe(object):
    def __init__(self):
        self.years = None
        self.months = None
        self.days = None

    def update(self, years=None, months=None, days=None):
        if years:
            self.years = years
        if months:
            self.months = months
        if days:
            self.days = days

class Picker(object):
    def __init__(self):
        self.picked = []

    def pick(self, item):
        do_it = self.picked.remove if \
            item in self.picked else self.picked.append
        do_it(item)
        self.notify(self)

    def set_notifier(self, notifier):
        self.notify = notifier

    def __iter__(self):
        for item in self.picked:
            yield item

    def __len__(self):
        return len(self.picked)

Code: Alles auswählen

>>> y = Picker()
>>> m = Picker()
>>> d = Picker()
>>> t = Timeframe()
>>> y.set_notifier(t.update)
>>> m.set_notifier(t.update)
>>> d.set_notifier(t.update)
>>> y.pick(2011)
>>> t.years
[2011]
Ist die erste Variante insofern in Ordnung, dass hier Timeframe() quasi 'unter der Hand' aktuell gehalten wird oder sollte, wie in meiner zweiten Variante ein 'Schmalspur-Observer-Pattern' verwendet werden?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wieso implementierst du mit `Picker()` das nach, was ein `set()` bereits kann?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu:
Aus 3 Gründen:
- Weil Picker() letztlich noch ein paar weitere Aufgaben, wie z. B. das Bereitstellen einer collection anzuzeigender Elemente, hat.
- Items, die bereits in 'picked' vorhanden sind, nicht nur kein weiteres Mal vorkommen sollen, sondern nach einer erneuten Auswahl wieder entfernt werden müssen. Dazu müsste ich dann auch bei einem set() eine Weiche einbauen, womit der Aufwand derselbe wie bei einer Liste ist.
- 'picked' während seiner weiteren Verwendung sortiert werden muss. Spätestens dann müsste ich eine Liste oder ein Tuple daraus machen.

Ich habe in meinen beiden Beispielen nur eine Kurzform von Timeframe() und Picker() abgebildet, weil es mir erstmal um die Frage geht, ob Picker-Exemplare ihre Veränderungen explizit mitteilen sollen oder man sich das dadurch sparen 'darf', wenn die Picker-Exemplare als Timeframe-Attribute gesetzt sind.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich weiß zwar nicht, was der tiefere Sinn sein soll, würde aber zu Beispiel 1 neigen und dann allerdings ein `t.years.pick(2011)` nutzen, weil das wesentlich klarer sein dürfte. Du kannst übrigens trotzdem ableiten, wenn auch nicht von einem `set()`. Ungetestet, weil ich weg muss:

Code: Alles auswählen

class Picker(list):
    def pick(self, elem):
        do_action = self.remove if (elem in self) else self.append
        do_action(elem)
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Was ist denn durch

Code: Alles auswählen

do_it = self.picked.remove if \
            item in self.picked else self.picked.append
        do_it(item)
gegenüber

Code: Alles auswählen

if item in self.picked:
    self.picked.remove(item)
else:
    self.picked.append(item)
gewonnen?
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu:
Ok, von 'list' abzuleiten macht Sinn.
Einen tieferen Sinn verfolgt das nicht wirklich, die Frage für mich ist, ab wann es angebracht ist, dass Objekt A bei einer Änderung ein Objekt B explizit darüber unterrichtet, auch oder obwohl sich Objekt A bereits als Attribut in Objekt B befindet und Objekt B deshalb nicht zwingendermaßen unterrichtet werden müsste.
Der Aufruf 't.years.pick(2011)' beantwortet mir da schon mal einiges. Ich war so auf die beiden Objekte 'timeframe' und 'picker' und ihre Verbindung miteinander konzentriert, dass ich die Kurve nicht bekommen hab'. Danke für den Hinweis, den ich eigentlich nicht mehr brauchen sollte... :oops:

@jbs:
Überhaupt nichts. Ich bin schon fast zwanghaft in solche Spielereien vernarrt... :wink:
Aber Du hast natürlich Recht, ich werde das ändern...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten