Seite 1 von 1
Bin neu hier und lerne ;-)
Verfasst: Dienstag 15. Januar 2013, 22:48
von Blaster
Hallo Gemeinde,
bin seit einigen Tagen hier angemeldet und absoluter Programmieranfänger.
Habe mir vorgenommen aus Spaß an der Freud ein wenig Python zu lernen.
Ich denke, da bin ich hier genau richtig
Um mir das gelernte ein wenig besser zu verdeutlichen habe ich mich an einem Rechen-"Parser" gewagt.
Ich bin irgendwie ziemlich erstaunt das ich das, wenn auch rudimentär, hinbekommen habe.
Anbei mein Code-Schnipsel des "Parser"
Vielleicht habt Ihr noch den ein oder anderen Verbesserungsvorschlag für mich!
Kann ich etwas vereinfachen oder sollte ich teile komplett anders gestalten?
Freue mich auf Eure positive Kritik und Anregung.
Grüße
Blaster
Code: Alles auswählen
#! /usr/bin/python
# -*- coding: utf-8 -*-
import re
print """
----------------------------------------------------------------------------
Es dürfen keine Leerzeichen zwischen Zahl und Operand stehen!
Am Ende der Formel muss ein = stehen.
Beispiel: 40*20/2+3=
----------------------------------------------------------------------------
"""
formel = raw_input ("Bitte gebe die Formel ein: ")
#Ist ein = am Ende der Formel?
#Wie lang ist die Formel?
if formel[len(formel)-1] == "=":
laenge = len(formel)
#Formel in eine Liste uebertragen
#formelListe = formel.split(" ")
formelListe = (re.split(r'(\D+)',formel))
#Feststellen wieviele Zahlen berechnet werden muessen
#Wieviele Operatoren sind vorhanden?
anzahlOps = 0
anzahlWerte = 0
for x in range(len(formelListe)):
if formelListe[x] == "*" or formelListe[x] == "/" or formelListe[x] == "+" or formelListe[x] == "-" or formelListe[x] == "=":
anzahlOps = anzahlOps + 1
else:
anzahlWerte = anzahlWerte +1
#Ist die Formel in Ordnung?
if anzahlOps >= anzahlWerte:
print """
------------------------------------------
In Deiner Formel befindet sich ein Fehler"
------------------------------------------
"""
#Rechnen
zs = float(formelListe[0])
for x in range(len(formelListe)):
if formelListe[x] == "*":
zs = zs * float(formelListe[x+1])
if formelListe[x] == "/":
zs = zs / float(formelListe[x+1])
if formelListe[x] == "-":
zs = zs - float(formelListe[x+1])
if formelListe[x] == "+":
zs = zs + float(formelListe[x+1])
print "Ergebnis:", zs
else:
print """
-----------------------------------------
!!! ACHTUNG - Es ist kein = vorhanden!!!!
Bitte starte das Programm neu.
-----------------------------------------
"""
Re: Bin neu hier und lerne ;-)
Verfasst: Dienstag 15. Januar 2013, 23:47
von BlackJack
@Blaster: Python kennt bei Sequenzen negative Indizes um relativ zum Ende der Sequenz auf Elemente zuzugreifen. Also zum Beispiel ``formel[-1]`` um auf das letzte Element zuzugreifen. Allerdings haben Zeichenketten auch eine Methode um zu testen ob sie mit einer bestimmten Teilzeichenkette enden. Die hat den Vorteil, dass sie auch bei einer leeren Zeichenkette keine Ausnahme auslösen.
Zur Konvention zur Schreibweise von Namen könntest Du mal einen Blick in den
Style Guide for Python Code werfen.
Konkrete Datentypen sollte man nicht in Namen verwenden, denn wenn man den Typ mal ändert, dann hat man entweder falsche und damit irreführende Namen im Quelltext, oder man muss die Namen überall ändern. Ausserdem sollte man Abkürzungen vermeiden die nicht allgemein bekannt sind.
Die Klammern um die rechte Seite von der Zuweisung an `formelListe` sind unnötig.
Quelltext der Form ``for i in range(len(sequence)):`` um dann mit `i` als Index auf die Elemente zuzugreifen ist in Python ein „anti pattern” weil man *direkt* über die Elemente iterieren kann, ohne den Umweg über einen Index. Falls man *zusätzlich* einen Index benötigt kann man die `enumerate()`-Funktion verwenden.
Statt der vielen ``or``\s hätte man einfach prüfen können ob das Element in einer Liste der Operatoren enthalten ist:
Code: Alles auswählen
operatoren_anzahl = 0
werte_anzahl = 0
for token in formel_token:
if token in ['+', '-', '*', '/', '=']:
operatoren_anzahl += 1
else:
werte_anzahl += 1
Dein Test ob die Formel in Ordnung ist nicht ausreichend. Der wäre auch zutreffend wenn man '+-*/42' eingibt. Und vor allem machst Du selbst wenn der Test feststellt, dass die Formel *nicht* in Ordnung ist, einfach weiter als wäre nichts passiert.
Beim Ausrechnen könnte man eine Indexschleife schreiben die bei 1 beginnt und in Zweierschritten weitergeht, aber eleganter wäre auch hier den Index weg zu lassen und mit einem Iterator zu arbeiten und sich die Elemente die man erwartet/braucht mit `next()` holen. Man könnte sich den rudimentären Test vorher auch sparen und hier gleich die Fehlerbehandlung einbauen.
Statt ``if`` für jeden Operator zu verwenden, sollte man mit ``elif`` arbeiten. Wenn man einen Operator gefunden hat macht es keinen Sinn das gleiche Element auch noch auf die anderen Operatoren zu testen.
Der Parser/Rechner kennt keinen Operatorvorrang. Das konnten selbst billige Taschenrechner in den 80ern schon.
Statt das alles auf Modulebene zu schreiben, hätte man das in Funktionen aufteilen können, die man separat testen und wiederverwenden könnte.
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 09:45
von Blaster
Vielen Dank für Deine Anregungen,
werde das ganze dann mal versuchen umzusetzen.
Eines habe ich nicht ganz verstanden.
Wenn ich "meine" Variablen mit den Konventionen des Style Guide vergleiche, kann ich nichts "schlechtes" an meinen Variablen finden.
Oder meinst Du die Namensgebung an sich?
Grüße
Blaster
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 10:18
von mutetella
Hallo,
was mir bezüglich Deiner Namensgebung auffällt:
formelListe -> formel_liste
Allerdings würde ich das gar nicht mehr an einen neuen Namen binden sondern einfach 'formel' beibehalten. Denn letztlich wandelst Du das, was an 'formel' gebunden ist ja nur in eine Liste um und arbeitest damit weiter.
anzahlOps -> anzahl_ops
Mein Vorschlag: 'operations'
anzahlWerte -> anzahl_werte
Mein Vorschlag: 'values'
zs -> Was verbirgt sich dahinter? Und: Weißt Du das auch in 2 Wochen noch?
Generell würde ich Dir auch raten, englische Begriffe für Deine Namen zu verwenden. Im Laufe der Zeit wirst Du sehen, dass sich für vieles bereits gängige (englische) Namen durchgesetzt haben und auch verwendet werden sollten. Damit versteht ein Außenstehender Deinen Code oftmals besser.
BlackJack hat es ja auch schon gesagt: Was sich für eine Datenstruktur hinter dem Namen verbirgt sollte sich nicht im Namen wiederfinden. Eine Nummer nenne ich z. B. 'number'. Sollte es sein, dass es auch mehr Nummern werden könnten oder schon sind, nenne ich das einfach 'numbers'.
mutetella
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 10:53
von snafu
@mutella: Naja, die "Rechenzeichen" heißen schon "Operatoren", nicht "Operationen". Letzteres steht eher für die konkrete Durchführung eine bestimmten Berechnung. An der Stelle geht es jedoch erstmal um die Analyse der Zeichen bzw Tokens. Auch eine Benennung mit "Anzahl" (engl. meist "num") finde ich nicht verkehrt, dass man ja keine Auflistung von Operatoren hat, sondern deren Vorkommen zählen möchte.
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 12:20
von jerch
Das leidige Thema Syntax der Namensgebung

Die Diskussion um Unterstrich- oder CamelCase-Notation kommt bei uns auch immer mal wieder auf. Der Styleguide von Python empfiehlt zwar die Unterstriche, ich würd das allerdings nicht so eng sehen und eher von den Rahmenbedingungen abhängig machen:
- will man was zur Pythonwelt beitragen --> an Sprachkonvention halten
- braucht man es intern --> auf Teamvorlieben bzw. Bibliothekabhängigkeit Rücksicht nehmen (z.B. Qt kommt CamelCase'd daher)
Gerade bei letzterem zeigt sich, dass die Leute von Java/C++/Obj-C kommend eher CamelCase bevorzugen.
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 12:38
von BlackJack
@jerch: Eine CamelCase-Diskussion findet man $GOTT sei Dank selten und auch bei C++/C#/Java/… macht man das ja nicht für die Namen um die es hier geht. Gegen CamelCase für etwas anderes als Klassennamen würde ich ganz entschieden sein. Bei den verbreiteten Sprachen kenne ich das nur von BASIC-Dialekten und Pascal. C++/C#/Java/… verwendet ausser für Klassen (und Konstanten) mixedCase.
Ich verstehe nicht so wirklich warum es so schwer ist sich an Konventionen zu halten. Bei Java verwenden die Leute doch auch keine_kleinbuchstaben_mit_unterstrichen sondern halten sich an die Gepflogenheiten dort. Und zwar ohne Diskussionen.
Bei Anbindungen an externe Bibliotheken, die in anderen Programmiersprachen geschrieben sind, ist es einfach nur pragmatisch die Namensgebung des Originals beizubehalten. Das kann man gerade bei GUIs auch ganz gut dazu verwenden um die Trennung GUI und Programmlogik durch die Namensgebung deutlich zu machen.
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 12:45
von EyDu
@jerch: Dein letzter Punkt ist doch kein Argument gegen die Verwendung des typischen Styles einer Sprache, sondern gegen die betreffenden Entwickler. Natürlich gibt es Situationen, in denen das Abweichen vom Standard sinnvoll ist: z.B. wenn man eine C++-Bibliothek ganz direkt wrapped oder wenn das zu erweiternde Modul bereits signifikant vom Standard abweicht.
Dein Argument klingt aber eher nach: warum sollten die armen Programmierer noch einen Style lernen, die kennen doch schon einen aus einer anderen Programmiersprache. Dabei ist die Formatierung des Quelltext viel mehr als ein wenig Dekoration. Typischerweise impliziert eine bestimmte Schreibweise oder ein bestimmtes Muster noch einige Informationen. Wenn man nach Hilfe sucht oder durch die Dokumentation geht, dann kann dieses Wissen enorm Hilfreich sein.
Hinzu kommt natürlich noch, dass jede Sprache auch eine gewisse Umwelt mitbringt. Typischerweise halten sich die mitgelieferten Module sehr nah am Standard. Mischt man das ganze nun noch mit seinen eigenen Standards, dann führt das gerne mal zu unübersichtlichem Quelltext, bzw. zu einem Mix verschiedenster Standards.
Re: Bin neu hier und lerne ;-)
Verfasst: Freitag 18. Januar 2013, 13:01
von jerch
@BlackJack und EyDu:
Naja, vllt liegts an "Was der Bauer nicht kennt..." - die Camel/mixedCase-Sache ist durch Java & Co. doch recht verbreitet. Die Unterstrich-Notation kenn ich eher von C her, und da "verliert" diese Form wohl gegen die Omnipräsenz in der Lehre von Java & Co. und macht Camel/mixedCase zum Quasistandard. Zumindest ein Erklärungsversuch, warum sich manche Leute so schwer tun damit und die Pythonempfehlung zuerst als fremdartig wahrnehmen.
Re: Bin neu hier und lerne ;-)
Verfasst: Montag 21. Januar 2013, 17:39
von Leonidas
jerch hat geschrieben:Die Unterstrich-Notation kenn ich eher von C her, und da "verliert" diese Form wohl gegen die Omnipräsenz in der Lehre von Java & Co. und macht Camel/mixedCase zum Quasistandard.
Quasistandard? Würde ich nicht unbedingt sagen, wenn ich mit so übliche Libraries anschaue sind die meist mit Underscores und manchmal auch alles zusammengeschieben. mixedCase sehe ich in C extrem selten und da ists dann meist auch jemand der nicht so Ahnung hat, der das so schreibt.
Re: Bin neu hier und lerne ;-)
Verfasst: Dienstag 22. Januar 2013, 09:44
von jerch
@Leonidas:
Ok, war vllt etwas missverständlich ausgedrückt. Was ich meinte, war, dass man in C kaum mixedCase findet (systemnah unter Windows sieht man z.B. noch viel Camel und mixedCase Varianten der ungarischen Notation) und die Unterstriche recht häufig anzutreffen sind.
So haben, bezogen auf die ersten 10 Sprachen des Tiobe-Indexes, eigentlich nur C, PHP und Python eine gewisse Unterstrichvorliebe. Das war mit Omnipräsenz von Java und Co gemeint.