__set__() aus __init__() heraus funktioniert nicht

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
ari
User
Beiträge: 1
Registriert: Sonntag 16. August 2009, 21:57

Moin,

Ich hab ne kleine Klasse gebaut, die nur bestimmte Werte annehmen soll:

Code: Alles auswählen

class choice(object):
    def __init__(self,possibilities,setting=None):
        try: possibilities.__contains__(1)
        except AttributeError: 
            raise TypeError, "not list,tuple or similar"
        self.poss = possibilities
        self.__set__(setting)
    
    def __set__(self, setting):
        if setting not in self.poss and setting != None:
            raise KeyError, "Aimed Setting not in Possibilities"
        else: self.setting = setting
    
    def __get__(self):
        return self.setting
Wenn man von außen setzen will, funktioniert das auch prima:

Code: Alles auswählen

foo = choice(("bar","baz",))
>>> foo = "bar"
>>> foo
'bar'
wenn ich das jetzt aber versuche mit dem zweiten parameter zu initialisiern, klappt das nicht:

Code: Alles auswählen

>>> foo = choice(("bar","baz",),"baz")
>>> foo
<struct.choice object at 0xb7deb22c>
was mache ich falsch? oder ist das etwa ein Bug?[/code]

danke schonmal, und grüße, Ari
lunar

Lerne Python. Dir ist doch offensichtlich gar nicht klar, was bei diesen Anweisungen überhaupt passiert. In Python kannst du den Zuweisungsoperator überhaupt gar nicht überladen.

Das erste Beispiel setzt also nicht – wie von Dir offensichtlich erwartet – den "Wert" des Objekts, sondern weist im Gegenteil dem Namen "foo" ein völlig neues Objekt (nämlich die Zeichenkette "bar") zu. Deswegen erhältst du auch die Ausgabe "bar", schließlich lässt Du da kein "choice"-Objekt mehr anzeigen, sondern ein "str"-Objekt.

Im zweiten Beispiel dagegen weist du den Namen "foo" nicht neu zu, er zeigt also immer noch auf dein "choice"-Objekt. Daher ist die Ausgabe des zweiten Beispiels völlig korrekt. Da du nicht definiert hast, wie sich ein "choice"-Objekt ausgeben soll, nutzt der Interpreter die Standardmethode, die eben Klassennamen und Speicheradresse ausgibt.

Wie Du die Zeichenkettenformatierung eines Objekts beeinflusst, steht in der Python-Dokumentation, die dazugehörigen Methoden sind ".__str__()" und ".__repr__()".

"Magische" Methoden wie ".__contains__()" sollte man übrigens auch nicht direkt aufrufen, sondern den entsprechenden Operator (in diesem Fall "in") verwenden.
BlackJack

@ari: Am Rande: Klassennamen sollten mit einem Grossbuchstaben beginnen, und ein Modul mit dem Namen `struct` gibt es auch schon in der Standardbibliothek.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Offenbar bist du über das Descriptor-Interface gestolpert, das aber völlig anders funktioniert.

Die Typprüfung würde ich auch anders machen, wenn man da ausversehen einen String übergibt kommt da ein völlig nichtssagendes:

Code: Alles auswählen

TypeError: 'in <string>' requires string as left operand
Also lieber ``if isinstance(possibilities, (list, tuple, set))``, oder die Prüfung ganz weglassen.
Antworten