Problem mit LEPL

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
MVXA
User
Beiträge: 2
Registriert: Sonntag 23. August 2009, 07:34

Hallo,
ich wollte mich mal an LEPL (http://www.acooke.org/lepl/) versuchen
und ein klein Taschenrechner programmieren.

Das Beispiel was man dort schon im Handbuch finden kann, habe ich
schon erfolgreich um die Fähigkeit mit Zahlen in der Decimal Klasse
aus dem decimal Modul zu rechnen erweitert und die Möglichkeit
eingebaut Zahlen als 2e-10 anzugeben. Es ist mir auch gelungen das
Beispiel um eine Klasse zu erweitern, die Variablen auflöst.

Im Augenblick versuche ich mich daran Zuweisungen zu erkennen und
automatisch zu verarbeiten. Leider gelingt mir dieser Punkt einfach nicht
und benötige hier Erleuchtung.

Als Ausgabe vom Script hätte ich erwartet:

Code: Alles auswählen

_VarAssignator
 +- 'A'
 `- AddOperation
    +- Decimal('1')
    `- Decimal('1')
Allerdings bekomme ich:

Code: Alles auswählen

_VarAssignator
 `- A AddOperation
 +- Decimal('1')
 `- Decimal('1')
Das Script kann man hier finden:
http://paste.pocoo.org/show/xNKnnS4TaUq1bV1pQRp5/

Danke für eure Antworten.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich kenne LEPL nicht und bin mir auch sicher, was du da machen willst. Doch wenn dein `_VarAssignator` nicht das ausgibt, was du willst, vielleicht hättest du dann nicht seine `__repr__`-Methode überschreiben sollen bzw. warum änderst du sie dann nicht passend?

Es würde IMHO zur Lesbarkeit des Codes beitragen, viele der `_` und alle Leerzeichen hinter und vor den Klammern wegzulassen.

Wenn ich's richtig verstehe, ich `VarAssignator` ein Konstruktor für `_VarAssignator`-Knoten. Warum nicht also einfach so?

Code: Alles auswählen

def VarAssignator(binding):
    class VarAssignator(lepl.Node):
        def value(self):
            binding[self[0]] = self[1].value()
    return lambda *args, **kwargs: VarAssignator(*args, **kwargs)
Das äußere `VarAssignator` (übrigens ein komischer Name) liefert, wenn aufgerufen, eine Funktion, die einen Knoten erzeugt. Da ich die Klasse erst in der Funktion definiere, ist `binding` in der Klasse als Teil ihrer Closure gebunden und ich kann mir das Zuweisen sparen. Und ich kann die Klasse genauso nennen wie die Funktion. Und, weil eine Klasse ja ebenfalls callable ist, kann ich's sogar noch einfacher machen:

Code: Alles auswählen

def VarAssignator(**mapping):
    class VarAssignator(lepl.Node):
        ...
    return VarAssignator
Den `VarResolver` kann man auf die selbe Weise einkürzen:

Code: Alles auswählen

def VarResolver(binding):
	class VarResolver(lepl.Node):
	    def value(self):
	        return decimal.Decimal(binding[self[0]])
	return VarResolver
Statt `_get_decimal` benutze ich einfach `value`.

Stefan
Benutzeravatar
MVXA
User
Beiträge: 2
Registriert: Sonntag 23. August 2009, 07:34

Nachdem ich etwas geschlafen habe, kann ich nun etwas klarer denken
und bin zum Schluss gekommen: Ich hab den Wald vor lauter Bäume
nicht mehr gesehen.

sma hat geschrieben:Ich kenne LEPL nicht und bin mir auch sicher, was du da machen willst.
Doch wenn dein `_VarAssignator` nicht das ausgibt, was du willst,
vielleicht hättest du dann nicht seine `__repr__`-Methode überschreiben
sollen bzw. warum änderst du sie dann nicht passend?
Nunja, ich habe das ganze etwas verschoben damit ich __str__ nutzen
konnte um an das Ergebnis des Terms zu kommen. Wie ich in meiner
Ausrede schon geschildert habe, habe ich aber übersehen, dass ich
eigentlich auch ganz einfach _get_value( ) aufrufen kann.
Es würde IMHO zur Lesbarkeit des Codes beitragen, viele der `_` und
alle Leerzeichen hinter und vor den Klammern wegzulassen.
Wenn ich in Sachen Programmieren eins gelernt habe, dann dass die
Frage des coding Stil eher eine Frage des Glaubens ist. Ich persönlich
halte den Code in der Form für lesbarer, als wenn ich auf alle Leerzeichen
verzichten würde.

Die _ sagen zumindest mir in welchem Sichtbarkeitsbereich sich die
Variable aufhält. m_* public _m_* protected __m_* private. Selbes
gilt auch für Funktionen, nur dass ich dort m_ weg lasse.

Das wurde mir allerdings auch schon mal im IRC Channel „vorgeworfen“.
Wie ich aber sagte, halte ich die Wahl des coding Stil für eine Frage des
Glauben.
sma hat geschrieben:Das äußere `VarAssignator` (übrigens ein komischer Name)
Finde ich auch, hast du vielleicht ein Besseren :wink: ? Saß da 4 Minuten
und mir fiel kein besserer Name für die Klasse ein.
sma hat geschrieben:Den `VarResolver` kann man auf die selbe Weise einkürzen:
Du hast recht. Dieser Trick ist mir eigentlich auch bekannt aber wie ich
schon erwähnte habe ich den Wald nicht mehr gesehen... :oops:. Ich
habe dein Vorschlag in der Hinsicht auch übernommen. Danke.
sma hat geschrieben:Statt `_get_decimal` benutze ich einfach `value`.
Ich habe die Methode nach _get_value( ) umbenannt. Auch hierfür
Danke für den Hinweis.

Im übrigen funktioniert der Code doch. Ich weiß nicht mehr warum ich
Heute Morgen noch Probleme damit hatte.
BlackJack

@MVXA: Ich weiss, ich weiss, es ist eine Stilfrage, aber das `m_` finde ich ziemlich unnütz. In C++ benutzt man das gerne um Membervariablen von lokalen Variablen zu unterscheiden, aber bei Python muss man ja immer explizit `self` verwenden, da ist das also schon deswegen klar. Und "Variablen" und "Funktionen" sollte man auch ohne `m_` anhand des Namens unterscheiden können, weil Funktionen nach einer Tätigkeit benannt werden sollten.
Antworten