Seite 1 von 1

Sinnvolle Parameterübergabe...

Verfasst: Dienstag 24. Mai 2011, 17:37
von mutetella
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

Re: Sinnvolle Parameterübergabe...

Verfasst: Dienstag 24. Mai 2011, 17:42
von 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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Dienstag 24. Mai 2011, 17:57
von Hyperion
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

Re: Sinnvolle Parameterübergabe...

Verfasst: Dienstag 24. Mai 2011, 18:33
von mutetella
Hyperion hat geschrieben:Was spricht denn gegen Keyword-Argumente?
Nichts!
Ich bin manchmal so vernagelt... :?

Danke!

mutetella

Re: Sinnvolle Parameterübergabe...

Verfasst: Mittwoch 25. Mai 2011, 16:45
von sma
Warum eigentlich ``getattr(self, 'title')`` und nicht einfach ``self.title``?

Stefan

Re: Sinnvolle Parameterübergabe...

Verfasst: Mittwoch 25. Mai 2011, 18:43
von mutetella
@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

Re: Sinnvolle Parameterübergabe...

Verfasst: Mittwoch 25. Mai 2011, 19:07
von BlackJack
@mutetella: Also ich würde von `self.__dict__` die Finger lassen.

Re: Sinnvolle Parameterübergabe...

Verfasst: Mittwoch 25. Mai 2011, 19:40
von mutetella
@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

Re: Sinnvolle Parameterübergabe...

Verfasst: Mittwoch 25. Mai 2011, 20:35
von BlackJack
@mutetella: Auch das würde ich wohl nicht machen. Geht das nicht expliziter?

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 06:44
von mutetella

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

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 08:22
von 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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 09:11
von mutetella
@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

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 09:33
von 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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 09:38
von mutetella
@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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 11:22
von 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 …

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 12:00
von 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...

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 12:15
von 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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 12:30
von mutetella
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

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 17:51
von snafu
@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.

Re: Sinnvolle Parameterübergabe...

Verfasst: Donnerstag 26. Mai 2011, 18:14
von 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). ;)