__repr__ Klassen benutzen wie Funktionen???

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
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 11. August 2004, 12:56

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?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 11. August 2004, 13:57

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
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 11. August 2004, 14:15

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...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 11. August 2004, 15:23

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
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 11. August 2004, 15:42

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...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 11. August 2004, 15:57

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
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 11. August 2004, 16:20

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...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 11. August 2004, 17:31

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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Gast

Mittwoch 11. August 2004, 18:53

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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 11. August 2004, 19:35

und wozu die Klasse?

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 11. August 2004, 20:19

(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...
Antworten