Sinnvolle Parameterübergabe...

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,

ich habe eine Methode, die momentan wie folgt aussieht:

Code: Alles auswählen

    def is_match(self, search_pattern):
        result = 0
        for area, value in search_pattern:
            if isinstance(value, datetime.date):
                result += self._is_base(value) or \
                    self._is_duration(value) or \
                    self._is_recurrence(value)
            elif area == 'all':
                result += value in getattr(self, 'title') or \
                    value in getattr(self, 'categorie') or \
                    value in getattr(self, 'longtext')
            else:
                result += value in getattr(self, area)
        return bool(result)
In dieser Form muss ich den Parameter 'search_pattern' so übergeben:

Code: Alles auswählen

is_match([('title', 'bla')])
oder

Code: Alles auswählen

is_match([('title', 'bla'), ('categorie', 'blub')])
wenn über mehrere Attribute gesucht werden soll.

Diese Form der Übergabe von einem oder mehreren search pattern finde ich nicht so ganz gelungen.
Mir fehlt aber auch gerade eine andere Idee... oder kann man das so machen?

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

Du kannst ein ellipsen-Argument nehmen, und dir damit eine Listen-Klammerung sparen:

Code: Alles auswählen

def foo(*patterns):
      ...

foo((a, b))
foo((a, b), (c, d), (e, f))

Du kannst sogar noch weiter gehen, und sowas machen

Code: Alles auswählen


def foo(*patterns):
     if len(patterns) ==2 and isinstance(patterns[0], basestring) and isinstance(patterns[1], basestring)):
        patterns = [patterns]
     for left, right in patterns:
          ...

foo(a, b)
Kommt halt drauf an, wie oft du den "nur ein pattern"-fall hast. Ich wuerde erstmal ohne auskommen wollen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was spricht denn gegen Keyword-Argumente? So wie ich das sehe, handelt es sich doch immer um Schlüssel-Wert-Paare. Dafür sind doch Dictsionaries und damit Keyword-Argumente prädestiniert:

Code: Alles auswählen

def is_match(**kwargs):
    for key, value in kwargs.iteritems():
        # usw
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hyperion hat geschrieben:Was spricht denn gegen Keyword-Argumente?
Nichts!
Ich bin manchmal so vernagelt... :?

Danke!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Warum eigentlich ``getattr(self, 'title')`` und nicht einfach ``self.title``?

Stefan
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@sma:
Weil ich auf umständliches Zeug steh'...? Nein, keine Ahnung, was mich da wieder geritten hat... :?

Inzwischen hab' ich die Methode aber sowieso nochmals umgeschrieben

Code: Alles auswählen

    def is_match(self, search_patterns):
        #TODO: search_patterns with 'and'
        result = 0
        if 'all' in search_patterns:
            for attr, value in self.__dict__.iteritems():
                if isinstance(value, basestring):
                    result += search_patterns['all'] in value
        else:
            for attr, value in search_patterns.iteritems():
                if isinstance(value, datetime.date):
                    result += self._is_base(value) or \
                        self._is_duration(value) or \
                        self._is_recurrence(value)
                else:
                    result += value in self.__dict__[attr]
        return bool(result)
Ist das ok so?

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

@mutetella: Also ich würde von `self.__dict__` die Finger lassen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack:
Ich hatte irgendwie im Kopf, dass ich schon einmal davon gelesen hätte, dass '__dict__' böse ist.
Ich weiß nur nicht mehr, warum... :(

Ich fand das jetzt praktisch, ein Verzeichnis mit allen Attributen zu haben. Welchen anderen Weg gibt es denn, um an die Attribute eines Exemplars zu kommen?

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

@mutetella: Auch das würde ich wohl nicht machen. Geht das nicht expliziter?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Code: Alles auswählen

def is_match(self, search_patterns):
        #TODO: search_patterns with 'and'
        result = 0
        text_attr = ['title', 'categorie', 'longtext']
        if 'all' in search_patterns:
            result = sum(map(lambda attr: search_patterns['all'] in
                getattr(self, attr), text_attr))
        else:
            for attr, value in search_patterns.iteritems():
                if isinstance(value, datetime.date):
                    result = self._is_base(value) or \
                        self._is_duration(value) or \
                        self._is_recurrence(value)
                else:
                    result = value in getattr(self, attr)
        return bool(result)
Bleiben für mich die Fragen: Warum würdest Du die Attributnamen explizit angeben? Und was spricht gegen '__dict__'?

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

@mutetella: Beides ist magisch. Wenn man die Attributnamen nicht irgendwo explizit angibt, kann man den Objekten keine Attribute mehr hinzufügen ohne dass die bei dieser Suchoperation mit berücksichtigt werden. Beispiel: Man nimmt die Berkeley-DB zum Speichern; die braucht eine Zeichenkette als Schlüssel; also hat man vielleicht plötzlich Objekte mit einem zusätzlichen Attribut `db_id`.

`__dict__` ist ein Implementierungsdetail. Das muss nicht vorhanden sein, oder wenn es vorhanden ist, müssen da auch nicht alle Attribute drin gespeichert sein.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Gilt das dann ähnlich auch für einen solchen Fall?
BlackJack hat geschrieben:Beides ist magisch.
Ok, das eine ist '__dict__' abzufragen. Und was ist das andere?

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

@mutetella: In dem anderen Thread hat lunar ja schon etwas dazu geschrieben.

Mit beides meinte ich neben dem `__dict__` dass einfach alle Attribute vom Typ Zeichenkette als zu durchsuchen angenommen werden. So etwas sollte man zumindest gut Dokumentieren, weil es halt überraschend ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Ja, deswegen habe ich ja dann auch auf '__subclasses__()' verzichtet...
Ich meine nur, kann es bei '__subclasses__()' auch sein, dass nicht verlässlich alle Unterklassen ausgegeben werden.
So wie Du das bei '__dict__' geschrieben hast, dass dort nicht zwingend alle Attribute vermerkt sind oder Attribute aufgeführt werden, mit denen nicht unbedingt zu rechnen war.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
lunar

@mutetella: "__subclasses__()" gibt zuverlässig alle noch existierenden Unterklassen einer Klasse zurück. Das hättest Du aber auch selbst in der Dokumentation nachlesen können …
deets

@lunar

wie ich gerade selbst nochmal testen musste fuer code in dem ich's brauchte: aber nur fuer die *unmittelbaren* unterklassen. Mann muss also einen kleinen traversierungs-Algorithmus bauen, wenn man alle unter-unter-*-Klassen haben will.

Allerdings mag ich __subclasses__ immer noch mehr als Meta-Klassen, mit denen man aehnliches erreichen, aber auch mehr Hirnwindungen verdrehen kann...
lunar

@deets: Stimmt, danke für die Korrektur. Allerdings steht das ja auch in der Dokumentation :)

Ich persönlich finde Lösungen, die solche speziellen Methoden verwenden, immer etwas magisch. Sie sind natürlich meistens ungeheuer praktisch, weil schnell implementiert, und daher manchmal ok, im Allgemeinen aber ziehe ich explizite Lösungen vor, auch mit Rücksicht auf andere, die möglicherweise nicht so viel Ahnung von Python haben. Das ist kein Vorwurf, ".__subclasses__()" oder gar Metaklassen sind ja nicht gerade alltägliche Werkzeuge, selbst für erfahrene Programmierer.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

lunar hat geschrieben:Das hättest Du aber auch selbst in der Dokumentation nachlesen können …
Nicht, dass ich das nicht getan hätte. Allerdings steht in der Dokumentation an anderer Stelle auch folgendes:
"object.__dict__
A dictionary or other mapping object used to store an object’s (writable) attributes.
"

Kein Wort über das, was BlackJack sagte, dass '__dict__' nicht zwingend vorhanden sein muss.

Und da Euer Wissen oft über mein Begreifen der Dokumentation hinausgeht, frage ich lieber... :wink:

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

@lunar: "Neue" Funktionen sind immer genau so lange exotisch, bis man sich an ihre Verwendung gewöhnt hat. Deine Argumentation könnte man auch für alle möglichen anderen Fälle nutzen. Was wohl stimmt, ist aber, dass so etwas nicht wirklich in "üblichem" Code vorkommt. Kann aber natürlich auch sein, dass bisher niemand auf die entsprechende Idee kam bzw es auf diese Art umsetzen wollte.
lunar

@snafu: Ich habe weder von „neuen Funktionen“ noch von „exotischen“ Funktionen gesprochen, sondern lediglich vom Unterschied zwischen einer expliziten Lösung und einer impliziten. Es ist eben durchaus ein Unterschied zwischen einer expliziten Beschreibung der abzufragenden Attribute, und einer impliziten Iteration über alle definierten Attribute mithilfe eines speziellen Attributs, oder zwischen einer expliziten Abbildung von Namen auf Klassen und einer implizite Iteration über alle Unterklassen einer Klasse.

Wenn Du nicht liest, was ich schreibe, kannst Du die Argumentation natürlich für alle möglichen anderen Fälle nutzen (oder eher missbrauchen). ;)
Antworten