Wie eigene Typen definieren?

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.
Benutzeravatar
snafu
User
Beiträge: 5537
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 18. September 2008, 11:09

Hi!

Ich plane mit einer Funktion namens prettify() die Objekte verschiedener anderer Funktionen, welche von diesen immer als Tuple-Liste zurückgegeben werden, lesbarer darzustellen. Hierfür müssten für jedes Listenelement die Elemente eines jeden Tuples mittels String Formattings in eine bestimmte Form gebracht und dann alle Elemente zu einem String zusammengefügt werden, welcher dann zurückgegeben wird. Bisher mache ich das so:

Code: Alles auswählen

def prettify_moods(data):
    s = []
    for elem in data:
        name, string, time, mood = elem
        s.append('<%s> %s <%s>\n%s' % (name, string, time, mood))
    return '\n\n'.join(s)
Ich möchte nun, dass in diesem Fall das Objekt data von der Funktion, die das Objekt zurückgibt (in meinem Fall heißt sie get_moods()) den Typ moods erhält, damit die spätere Funktion prettify() prüfen kann, um welchen Typ es sich handelt und dann entscheidet, wie das entsprechende String Formatting aussehen muss.

Das war quasi die Erklärung für die Frage aus der Überschrift - ich hoffe, es ist nachvollziehbar, was ich vorhabe. :)

Gruß

Sebastian
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Donnerstag 18. September 2008, 11:16

Also ich verstehe nicht, was du willst. Suchst du danach?

Code: Alles auswählen

class Mood(object):
    ...

def get_moods():
    return [Mood(), Mood(), ...]

for obj in get_moods():
    if isinstance(obj, Mood):
        ...
Stefan
BlackJack

Donnerstag 18. September 2008, 11:20

Deine Frage im Titel geht schon in die richtige Richtung: Deine Objekte sollten selber wissen wie sie "prettified" werden, also musst Du Typen erstellen, die eine entsprechende Methode haben. Eigene Typen erstellt man mit ``class``. Das allgemeine `prettify()` sähe dann ungefähr so aus:

Code: Alles auswählen

def prettify(data):
    return '\n\n'.join(d.prettify() for d in data)
Der Ansatz, den sma da zeigt, ist eher unschön.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Donnerstag 18. September 2008, 11:33

http://pypi.python.org/pypi/simplegeneric

Das dürfte vielleicht passen :)
Benutzeravatar
snafu
User
Beiträge: 5537
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 18. September 2008, 11:35

BlackJack hat geschrieben:Eigene Typen erstellt man mit ``class``.
Sorry, das habe ich nicht ganze verstanden. Wenn ich die Klasse Test erstelle, hat sie doch immer noch den Typ instance:

Code: Alles auswählen

>>> class Test:
	pass

>>> test = Test()
>>> type(test)
<type 'instance'>
Davon habe ich ja nicht wirklich was. Aber vermutlich meintest du das auch anders...
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 18. September 2008, 11:43

Eigene Typen definierst du mit ``class``. Eine Klasse ist ein Typ, so einfach ist das. Und jeder Typ weiß, wie man sich darstellt, über ``render``. Oder irgendeine andere Funktion.

Code: Alles auswählen

class RenderingNode(object):
    def render(self):
        return self.content

class Text(RenderingNode):
    def __init__(self, text):
        self.content = text

class Number(RenderingNode):
    def __init__(self, number):
        self.content = number

nodes = [Text("Ich bin"), Number(3), Text("Jahre alt")]
print ' '.join(node.render() for node in nodes)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 18. September 2008, 11:51


CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
snafu
User
Beiträge: 5537
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 18. September 2008, 13:21

Vielleicht verstehe ich euch alle nur falsch, aber ich möchte eigentlich sowas machen können:

Code: Alles auswählen

def prettify(data):
    datatype = type(data)
    if datatype is moods:
        return _prettymoods(data)
    if datatype is bulletins:
        return _prettybulletins(data)
    else:
        raise TypeError, 'Expect moods or bulletins type, not %s' % datatype

def _prettymoods(data):
    hier der selbe inhalt wie oben beschrieben
Und mir ist bisher nicht klargeworden wie ich das umsetzen soll.
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Donnerstag 18. September 2008, 13:39

Du suchst wohl nach isinstance()?
Und natürlich hat eine Instanz einer Klasse den Typ Instanz ;)
Klassenvergleiche kannst du dann mit isinstance machen.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 18. September 2008, 13:42

snafu hat geschrieben:Vielleicht verstehe ich euch alle nur falsch, aber ich möchte eigentlich sowas machen können:
Leonidas variante mit render() ist aber IMHO besser.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 18. September 2008, 14:16

snafu hat geschrieben:Vielleicht verstehe ich euch alle nur falsch, aber ich möchte eigentlich sowas machen können
Das ist aber keine gute idee, da die Render-Logik dann in eine ungebeiligte Funktion verschoben wird, die zudem nicht erweiterbar ist. Meine Variante ermöglicht belibige Erweitarbarkeit, da um es zu rendern nur ein Interface implementiert werden muss, schon funktioniert das Rendern wie mit bereits fertigen Klassen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Donnerstag 18. September 2008, 15:08

Das Prinzip, das Leonidas vorgeschlagen hat, ist doch dabei eine wirklich gängige und sinnvolle Lösung. Spontan fällt mir bei Java die toString()-Methode ein, die afaik jedes Objekt besitzt.

Ok, bei Python ja auch fällt mir grad auf :-D

Will man eine eigene Form der Ausgabe überschreibt man eben __str__() oder __repr__() und voila. Nichts anderes wird doch von Dir verlangt, oder?
Benutzeravatar
snafu
User
Beiträge: 5537
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 18. September 2008, 16:34

Habe Leonidas' Tipp nun erfolgreich angewendet: http://paste.pocoo.org/show/85606/

Vielen Danke dafür. :)

Anmerkung: Die fehlenden Klammern in Zeile 53 sind mir später auch aufgefallen und bei mir nun gesetzt. ;)
BlackJack

Donnerstag 18. September 2008, 16:51

Nein, Du hast Leonidas' Tipp nicht erfolgreich angewendet. Warum kannst oder willst Du den Klassen, die Du *sowieso schon hast*, keine `prettify()`-Methode verpassen? So wie's jetzt ist, ist es ja noch bescheuerter gelöst als die hässliche Nicht-OOP-Lösung mit Typtests. `Toolbox` ist im Moment vollkommen überflüssig.
Benutzeravatar
snafu
User
Beiträge: 5537
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 18. September 2008, 20:27

BlackJack hat geschrieben:Nein, Du hast Leonidas' Tipp nicht erfolgreich angewendet. Warum kannst oder willst Du den Klassen, die Du *sowieso schon hast*, keine `prettify()`-Methode verpassen? So wie's jetzt ist, ist es ja noch bescheuerter gelöst als die hässliche Nicht-OOP-Lösung mit Typtests. `Toolbox` ist im Moment vollkommen überflüssig.
Hab's in der neuen Version beachtet: http://paste.pocoo.org/show/85627/
Antworten