Seite 1 von 1

__repr__ Klassen benutzen wie Funktionen???

Verfasst: Mittwoch 11. August 2004, 12:56
von jens
Hallo...

Ich möchte öfters mal Klassen wie einfache Funktionen benutzen...
Dazu dachte ich, liefert mir __repr__ das Ergebniss zurück, da ja leider __init__ kein Ergebniss zurück liefern kann...

Mit __repr__ scheint es auch zu funktionieren, aber als ich zwei Aufrufe hintereinander Ausführen wollte, ist mir Aufgefallen, das __repr__ nicht einen String, sondern eine Instanz zurückliefert :(

Hier mal ein Beispiel:

Code: Alles auswählen

class test1:
    def __init__(self, text):
        self.text=text

    def __repr__(self):
        return self.text+" test1"


class test2:
    def __init__(self, text):
        self.text=text

    def __repr__(self):
        return self.text+" & test2"

text=test1("Hello World:")
print type(text),":",text

text=test2(text)
print type(text),":",text
Das Ergebniss:

Code: Alles auswählen

<type 'instance'> : Hello World: test1
<type 'instance'> : Traceback (most recent call last):
  File "testtemp.py", line 50, in ?
    print type(text),":",text
  File "testtemp.py", line 44, in __repr__
    return self.text+" & test2"
TypeError: unsupported operand type(s) for +: 'instance' and 'str'


Schade...
Eine Lösung ist es in der Klasse eine "get"-Funktion einzubauen... Das funktioniert auch:

Code: Alles auswählen

class test1:
    def __init__(self, text):
        self.text=text

    def get(self):
        return self.text+" test1"


class test2:
    def __init__(self, text):
        self.text=text

    def get(self):
        return self.text+" & test2"

text=test1("Hello World:").get()
print type(text),":",text

text=test2(text).get()
print type(text),":",text
Liefert das Ergebniss, so wie ich es vom ersten beispiel mit __repr__ auch erwartet habe:

Code: Alles auswählen

<type 'str'> : Hello World: test1
<type 'str'> : Hello World: test1 & test2

Der Nachteil bei der zweiten Variante ist aber, das man halt den Aufruf mit .get() ergänzen muß...

Gibt es einen einfacheren Weg?

Verfasst: Mittwoch 11. August 2004, 13:57
von Dookie
Hi jens,

Du scheinst da was missverstanden zu haben.
__repr__ soll eine "representative" Anischt eines Objekts liefern. Im besten Fall soll diese Ansicht, an die eingebaute Funktion eval übergeben, ein Objekt mit den gleichen Eigenschaften zurückgeben.
In Deinem Speziellen Fall kannst Du __str__ in der Klasse definieren:

Code: Alles auswählen

class test1:
    def __init__(self, text):
        self.text=text

    def __str__(self):
        return self.text
Ganz sauber gehts mit mit Newstyleklassen.

Code: Alles auswählen

class test(object):
    __slots__ = ["text"]

    def __new__(cls, text):
        self = super(test, cls).__new__(cls)
        self.text = text
        return self

    def __str__(self):
        return self.text

Gruß

Dookie

Verfasst: Mittwoch 11. August 2004, 14:15
von jens
Mit __str__ geht es leider auch nicht... Man erhält nur wieder eine Instanz:

Code: Alles auswählen

class test1:
    def __init__(self, text):
        self.text=text

    def __str__(self):
        return self.text+" test1"


class test2:
    def __init__(self, text):
        self.text=text

    def __str__(self):
        return self.text+" & test2"

text=test1("Hello World:")
print type(text),":",text

text=test2(text)
print type(text),":",text

Code: Alles auswählen

<type 'instance'> : Hello World: test1
<type 'instance'> : Traceback (most recent call last):
  File "testtemp.py", line 50, in ?
    print type(text),":",text
  File "testtemp.py", line 44, in __str__
    return self.text+" & test2"
TypeError: unsupported operand type(s) for +: 'instance' and 'str'
Die Newstyleklassen sind wesentlich Aufwendiger zu realisieren als mit einer "get"-Funktion, die auch Flexibler ist...

Verfasst: Mittwoch 11. August 2004, 15:23
von Dookie

Code: Alles auswählen

class test1:
    def __init__(self, text):
        self.text=str(text)

    def __str__(self):
        return self.text+" test1"


class test2:
    def __init__(self, text):
        self.text=str(text)

    def __str__(self):
        return self.text+" & test2"

text=test1("Hello World:")
print type(text),":",text

text=test2(text)
print type(text),":",text
geht doch, nur musst die Instanz in einen String umwandeln.


Gruß

Dookie

Verfasst: Mittwoch 11. August 2004, 15:42
von jens
Du hast recht... Es funktioniert... Dennoch sind es Instanzen:

Code: Alles auswählen

<type 'instance'> : Hello World: test1
<type 'instance'> : Hello World: test1 & test2
Ich weiß nicht recht, ob das so gut ist...
Wenn ich danach mit dem Ergebniss wie mit einem String umgehen will, geht das nicht:

Code: Alles auswählen

print text+" noch etwas..."

Code: Alles auswählen

TypeError: unsupported operand type(s) for +: 'instance' and 'str'
Es geht natürlich so:

Code: Alles auswählen

print str(text)+" noch etwas..."
Aber so glücklich bin ich damit nicht... ich denke es können sich so Fehler einschleichen...

Verfasst: Mittwoch 11. August 2004, 15:57
von Dookie
Du könntest auch direkt von str ableiten

Code: Alles auswählen

class test1(str):
    def __new__(cls, text):
        return super(test1, cls).__new__(cls, text+" test1")

class test2(str):
    def __new__(cls, text):
        return super(test2, cls).__new__(cls, text+" & test2")

text=test1("Hello World:")
print type(text),":",text

text=test2(text)
print type(text),":",text

Gruß

Dookie

Verfasst: Mittwoch 11. August 2004, 16:20
von jens
Danke, aber das ist mir zu kompliziert... :x

Ursprünglich dachte ich __repr__ ist nur einfach durch ein anderes __???__ zu ersetzten und schon klappt es...

Verfasst: Mittwoch 11. August 2004, 17:31
von gerold
Hallo!

Und jetzt kommt auch noch mein Senf dazu 8)

Code: Alles auswählen

class Hallo(object):
    def gib_mir_ein_hallo(self):
        return "Hallo"

    def __call__(self):
        return self.gib_mir_ein_hallo()

h = Hallo()
print h()
So kann zwar die Klasse nicht direkt wie eine Funktion angesprochen werden, aber eine Instanz davon.
Vieleicht genügt dir das ja bereits. Wenn du so etwas öfter machst, kannst du dir ja immer noch eine Funktion schreiben, die zuerste eine Instanz einer Klasse erstellt, eine Methode dieser Klasse aufruft und dir das Ergebnis zurück liefert.

Code: Alles auswählen

def hallo_helper():
    h = Hallo()
    return h.gib_mir_ein_hallo()
mfg
Gerold
:-)

Verfasst: Mittwoch 11. August 2004, 18:53
von Gast
gerold hat geschrieben:Wenn du so etwas öfter machst, kannst du dir ja immer noch eine Funktion schreiben, die zuerste eine Instanz einer Klasse erstellt, eine Methode dieser Klasse aufruft und dir das Ergebnis zurück liefert.
Genau so mache ich es bisher:

Code: Alles auswählen

class test:
    def get(self,text):
        return text+" test"

def mache(text):
    return test().get(text)

text=mache("Hello World:")
print type(text),":",text

Verfasst: Mittwoch 11. August 2004, 19:35
von Dookie
und wozu die Klasse?

Dookie

Verfasst: Mittwoch 11. August 2004, 20:19
von jens
(Oh, da war ich wohl nicht eingeloggt)


Bei diesem Beispiel macht es natürlich keinen Sinn eine Klasse Aufzubauen :)
Eigentlich geht es um größere Klassen mit ein paar Funktionen...