Ein Notenprogramm (Artikel + Skript)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Ich habe mir (anlässlich des Semesterendes) ein kleines Skript geschrieben, dass mir sagt, wie viel ich in der nächsten Prüfung leisten muss um auf einen bestimmten Durchschnitt zu kommen. Hier der Code:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
    
# Notenrechner - unterstützt Schüler beim Ausrechnen ihres Notendurchschnitts
# Copyright (C) 2008  Patrick Bucher

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

# Initialisierung
print "\nNotenprogramm\n", '-' * len("Notenprogramm")
noten = []

# Bisher erreichte Noten einlesen
while True:
  tmp = float(raw_input("Geben Sie eine Note ein (1 bis 6, 0 = Abbruch):\t"))
  if 1 <= tmp <= 6:
    noten.append(tmp)
  elif tmp == 0:
    break
  else:
    print "Falsche Eingabe!\n"

if not len(noten):
  exit()

# Durchschnitt ausgeben
notensumme = 0.0
for tmp in noten:
  notensumme += tmp

durchschnitt = notensumme / len(noten)
print "\nIhr aktueller Durchschnitt: %.2f\n" % durchschnitt

# Ziel-Durchschnittsnote einlesen
while True:
  target = float(raw_input("Geben Sie Ihre Ziel-Durchschnittsnote ein:\t"))
  if 1 <= target <= 6:
    break
  else:
    print "Falsche Eingabe!\n"

# Bei der nächsten Prüfung zu erreichende Note ausrechnen
todo = target * (len(noten) + 1) - notensumme

# Ausgabe
if todo > 6:
  maximal = (notensumme + 6) / (len(noten) + 1)
  print "\nZiel unerrreichbar! Maximaler Durchschnitt (mit Note 6): %.2f\n" % maximal
elif todo < 1:
  minimal = (notensumme + 1) / (len(noten) + 1)
  print "\nZiel unerreichbar!: Minimaler Durchschnitt (mit Note 1): %.2f \n"  % minimal
else:
  print "\nBei der nächsten Prüfung müssen Sie die Note %.2f erreichen!\n" % todo

raw_input()
Ein ausführlicher Artikel dazu ist hier zu finden.

Verbesserungsvorschläge? :)

Edit (Leonidas): Code-Highlighting eingeschaltet.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ohne mir das Programm genauer angesehen zu haben: Wieso liest du die Noten als Floats ein? Auf meinen Schulaufgaben standen bisher die Noten immer als Integer drauf.

Floats haben auch das Problem, dass 0.0 nicht immer gleich 0 ist. Nichtmal 0.0 == 0.0 ist mit Sicherheit gleich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

*g* Nette Idee sich ein wenig unter Druck zu setzen :D

So, ne kleine Verbesserungsidee:
Wieso packst Du das nicht in eine main() Funktion?
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Vllt möchte er dadurch eine 1- (1,3) ermöglichen.
Mephisto
User
Beiträge: 28
Registriert: Mittwoch 17. Januar 2007, 15:52

Also auf meiner FH sind die Noten floats, ich nehm an bei ihm ist das auch so (weis garnicht ob das irgendwie allgemein geregelt ist). Auf jeden Fall kann auch 1.3 oder 2.7 oder sonstwas schreiben :)

greets meph
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Leonidas hat geschrieben:Ohne mir das Programm genauer angesehen zu haben: Wieso liest du die Noten als Floats ein? Auf meinen Schulaufgaben standen bisher die Noten immer als Integer drauf.
Bei uns (in der Schweiz) arbeiten alle Lehrerobjekte mit floats! :wink: Im Semesterzeugnis wird dann in der Regel auf 0.5 Notenpunkte genau gerundet.
Die skurrilste Note die ich je erhalten habe war eine theoretische 7.8829, die dann jedoch auf 6 abgerundet werden musste :D
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ok, gut, dann weiß ich das mal, danke. Trotzdem wird Zeile 30 nicht und wenn doch dann nur zufällig und nicht mit Sicherheit funktionieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Leonidas hat geschrieben:Ok, gut, dann weiß ich das mal, danke. Trotzdem wird Zeile 30 nicht und wenn doch dann nur zufällig und nicht mit Sicherheit funktionieren.
Achso, jetzt verstehe ich deinen Einwand! Die Eingabe des Benutzers, die von 0 zu 0.0 konvertiert wird, wird mit dem fix codierten Wert 0 verglichen:

Code: Alles auswählen

0 == 0.0
Naja, das ist nicht wirklich schön!

Danke für den Hinweis.
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Hast du mal ein Beispiel für 0 != 0.0 ?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hobbes Hobson hat geschrieben:Hast du mal ein Beispiel für 0 != 0.0 ?

Code: Alles auswählen

>>> ((3.1 ** 2) - 9.61) != 0
>>> True
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Das las ich so nicht gelten.

9.61-(3.1**2) --> -1.7763568394e-015

Er vergleicht aber 0.0 mit 0.
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Hobbes Hobson hat geschrieben:Das las ich so nicht gelten.

9.61-(3.1**2) --> -1.7763568394e-015

Er vergleicht aber 0.0 mit 0.
Wenn der Benutzer von sich aus -1.7763568394e-015 eingibt, dann müsste er in meinem Skript halt die Eingabe wiederholen. :wink:
Für mein Skript macht das keinen Unterschied, generell ist der Einwand aber sehr wohl berechtigt! Und damit man es sauber lernt, sollte man es immer richtig machen. So ist der Einwand meiner Meinung nach zu begründen.
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Ich habe das jetzt etwas abgeändert, heißt in Funktionen gepackt.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding:  iso-8859-15 -*-
from __future__ import division

def eingabe():
  print "\nNotenprogramm\n", '-' * len("Notenprogramm")
  noten = []

  # Bisher erreichte Noten einlesen
  try:

    while True:
      tmp = raw_input("Geben Sie eine Note ein (1 bis 6, Ctrl + C = Abbruch):\t")
      print tmp
      try:
        tmp = float(tmp)
      except ValueError:
        print "Falsche Eingabe (value error)!\n"
      else:
        if 1 <= tmp <= 6:
          noten.append(tmp)
        else:
          print "Falsche Eingabe (out of range)!\n"

  except KeyboardInterrupt:
    if not noten:
      exit()
    return noten

def verarbeitung(noten):
  # Durchschnitt ausgeben
  notensumme = sum(noten)

  durchschnitt = notensumme / len(noten)
  print "\nIhr aktueller Durchschnitt: %.2f\n" % durchschnitt

  # Ziel-Durchschnittsnote einlesen


  while True:
      target = raw_input("Geben Sie Ihre Ziel-Durchschnittsnote ein:\t")
      try:
        target = float(target)
      except ValueError:
        print "Falsche Eingabe (value error)!\n"
      else:
        if 1 <= target <= 6:
          break
        else:
          print "Falsche Eingabe (out of range)!\n"

  # Bei der nächsten Prüfung zu erreichende Note ausrechnen
  todo = target * (len(noten) + 1) - notensumme

  if todo > 6: (-1,(notensumme + 6) / (len(noten) + 1))
# Ausgabe
  elif todo <1: return (-1, (notensumme + 1) / (len(noten) + 1))
  else: return 0, todo

def ausgabe((flag, resnote)):
  if flag > 0:  print "\nZiel unerrreichbar! Maximaler Durchschnitt (mit Note 6): %.2f\n" % resnote
  elif flag < 0:  print "\nZiel unerreichbar!: Minimaler Durchschnitt (mit Note 1): %.2f \n"  % resnote
  else: print "\nBei der nächsten Prüfung müssen Sie die Note %.2f erreichen!\n" % resnote

def main():
  ausgabe(verarbeitung(eingabe()))

if __name__ == '__main__':
  main()

Ist ein KeyboardInterrupt ein gängiges Mittel zum Abbruch einer Eingabe? Ich habe es immerhin so in der Schule gelernt ;)
Zuletzt geändert von Hobbes Hobson am Sonntag 6. Januar 2008, 00:43, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hobbes Hobson hat geschrieben:Ist ein KeyboardInterrupt ein gängiges Mittel zum Abbruch einer Eingabe? Ich habe es immerhin so in der Schule gelernt ;)
Ja.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Danke für die Tipps! Auf Exceptions wird dann im siebten Teil meines Buches "Einführung in Python" eingegangen, im Moment bin ich noch bei der OOP. Und dann wären meine Ferien auch schon wieder zu Ende... :roll:
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Eine Sache die mir aufgefallen ist: Verwende als Einrückungen 4 statt 2 Leerzeichen. Ist schöner zu lesen und ist auch Konvention.
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Hobbes Hobson hat geschrieben:Eine Sache die mir aufgefallen ist: Verwende als Einrückungen 4 statt 2 Leerzeichen. Ist schöner zu lesen und ist auch Konvention.
Schöner zu lesen, naja. Das ist nun wirklich Geschmackssache. Aber wo steht denn etwas von Konvention "4 Leerschläge"? Das scheine ich bisher immer überlesen zu haben...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

paedubucher hat geschrieben:Aber wo steht denn etwas von Konvention "4 Leerschläge"? Das scheine ich bisher immer überlesen zu haben...
PEP 8.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
paedubucher
User
Beiträge: 30
Registriert: Donnerstag 29. Juni 2006, 18:29
Wohnort: Schweiz
Kontaktdaten:

Leonidas hat geschrieben:
paedubucher hat geschrieben:Aber wo steht denn etwas von Konvention "4 Leerschläge"? Das scheine ich bisher immer überlesen zu haben...
PEP 8.
OK, das sieht recht offiziell aus :D
Ich werde mich dann wohl umgewöhnen müssen... bzw. .vimrc ändern :wink:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ok, ich mag keine vollständigen quotes, aber der Post ist einfach zu kurz:
Hobbes Hobson hat geschrieben:Das las ich so nicht gelten.
9.61-(3.1**2) --> -1.7763568394e-015
Er vergleicht aber 0.0 mit 0.
Und jetzt berechnest du am besten noch mal per Hand aus, was bei 9.61-(3.1^2) raus kommst und wirst feststellen, dass dies 0 ist 8)

Edit: Ich sollte vielleicht kurz auf Numerik verweisen, nicht dass ich die tausendste Diskussion über solche Probleme lostrete.
Antworten