Mein erstes kleines Programm...

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
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

... will nicht ganz funktionieren. Ich dachte mir, ich programmiere mir mal ein kleines Kalkulationsprogramm. Hier der Code:

Code: Alles auswählen

# -*- coding: utf-8 -*-
from __future__ import division
from decimal import Decimal
import sys

# Informationen zum Programm
ProduktName = "Kalkulationsschema fuer den Einzelhandel"
CopyRight = "©"
Autor = "Sophus"
Jahr = "2014"
Version = "Built 0.1"
DankSagung = "Mitgliedern des deutschen Python-Forum"
URL_Forum ="http://www.python-forum.de/"
Feature1 = "Beschaffungskalkulation(Vorwaerts)"
Feature2 = "Beschaffungskalkulation(Rueckwaerts)"
Feature3 = "Differenzkalkulation"
Feature4 = "Absatzkalkulation"

print "================================ Hilfe ================================="
print " Tastenkuerzel: - E (Programm beenden)"
print ""
print "================================ Info =================================="
print " Willkommen bei " + "'" + ProduktName + "'" + " ( " + Version + " )"
print " Dieses Programm wurde von " + CopyRight + " " + Autor + "(" + Jahr + ") geschrieben."
print ""
print "================================ Danksagung ============================"
print " An dieser Stelle moechte ich mich bei den "
print " "+ DankSagung + " bedanken."
print " URL: " + URL_Forum
print ""
print "================================ Menu ==================================" 
print " Folgende Features sind enthalten:"
print "                     (1)" + Feature1
print "                     (2)" + Feature2
print "                     (3)" + Feature3
print "                     (4)" + Feature4
print ""
print "================================ Programm ==============================" 
print ""


class calcu (object):
    def __init__(self):
        
        # Anwender soll sich ein Feature (Methode) aussuchen
        def start(self):
            VarDict ={"1":Feature1, "2":Feature2, "3": Feature3, "4": Feature4}
                
            Eingabe = raw_input(""" Waehlen Sie ein Feature aus dem Menu, indem sie die entsprechende
                         Zahl eingeben! """)
            MyString = ' Sie haben sich fuer das folgende Feature entschieden: '
            print MyString + VarDict[Eingabe]
            if Eingabe == "1":
                BKV()   # Beschaffungskalkulation(Vorwaerts)-Methode aufrufen
            if Eingabe == "2":
                BKVR()  # Beschaffungskalkulation(Rueckwaerts)-Methode aufrufen
            if Eingabe == "3":
                DK()    # Differenzkalkulation-Methode aufrufen
            if Eingabe == "4":
                AK()    # Absatzkalkulation-Methode aufrufen
            if Eingabe >= 4: #Keine Methode aufrufen
                print "Falsch"
            
        def BKV(self): # Beschaffungskalkulation(Vorwaerts)
            print ""
            print " Die " + Feature1 + " wurde gestartet."
            print ""
            LP = float(raw_input(" Listenpreis: "))
            LR = float(raw_input(" - Lieferantenrabatt (%): "))
            ZKP = Decimal(LP-LP*LR/100)
            R_ZKP = round(ZKP, 2)
            print " = Zieleinkaufspreis: " + str(R_ZKP) + " Euro"
            print "-----------------------"
            LSK = float(raw_input (" - Lieferantenskonto (%) "))
            BKP = Decimal(R_ZKP-R_ZKP*LSK/100)
            R_BKP = round(BKP, 2)
            print " = Bareinkaufspreis: " + str(R_BKP) + " Euro"
            print "-----------------------"
            BZK= float(raw_input("+ Bezugskosten "))
            BZP = Decimal(BZK+R_BKP)
            R_BZP = round(BZP, 2)
            print " = Einstandspreis (Bezugspreis) " + str(R_BZP) + " Euro"
            print "-----------------------"
            GMK = float(raw_input(" + Gemeinkosten / Handlungskosten (%): "))
            SKP = Decimal(R_BZP+(GMK*R_BZP)/100)
            R_SKP = round(SKP, 2)
            print " = Selbstkosten: " + str(R_SKP) + " Euro"
            print "-----------------------"
            GZS = float(raw_input(" + Gewinnzuschlag (%): "))
            BVKP = Decimal(R_SKP+(R_SKP*GZS)/100)
            R_BVKP = round(BVKP, 2)
            print " = Barverkaufspreis: " + str(R_BVKP) + " Euro"
            print "-----------------------"
            KSK = float(raw_input(" + Kundenskonto (%): "))
            VP = float(raw_input(" + Vertreterprovision (%): "))
            KSK_Zwsichenschritt = Decimal(R_BVKP*KSK/(100-KSK-VP))
            R_KSK_Zwsichenschritt = round(KSK_Zwsichenschritt, 2)
            VP_Zwischenschritt = Decimal(R_BVKP*VP/(100-KSK-VP))
            R_VP_Zwischenschritt = round(VP_Zwischenschritt, 2)
            ZVP = Decimal(R_BVKP+(R_KSK_Zwsichenschritt+R_VP_Zwischenschritt))
            R_ZVP = round(ZVP, 2)
            print " = Zielverkaufspreis: " +str(R_ZVP) + " Euro"
            print "-----------------------"
            KR = float(raw_input(" + Kundenrabatt: "))
            LVKP_netto = Decimal(R_ZVP/(100-KR)*100)
            R_LVKP_netto = round(LVKP_netto, 2)
            print " = Listenverkaufspreis (netto): " + str(R_LVKP_netto) + " Euro"
            print "-----------------------"
            UST = float(raw_input(" + Umsatzsteuer (%): "))
            LVKP_brutto = Decimal(R_LVKP_netto+R_LVKP_netto/100*UST)
            R_LVKP_brutto = round (LVKP_brutto, 2)
            print " = Listenverkaufspreis (brutto): " + str(R_LVKP_brutto) + " Euro"
            print "======================="
                           
                
        def BKVR(self): # Beschaffungskalkulation(Rueckwaerts)
            print ""
            print """ HINWEIS: Dieses Feature ist noch in Arbeit. Bei der naechsten
                Aktualisierung wird das von Ihnen gewuenschte Feature freigeschalten."""
    
        def DK(self): # Differenzkalkulation
            print ""
            print " Die " + Feature3 + " wurde gestartet."
            print ""
            LP = float(raw_input(" Listenpreis: "))
            LR = float(raw_input(" - Lieferantenrabatt (%): "))
            ZKP = float(Decimal(LP-LP*LR/100))
            R_ZKP = round(ZKP, 3)
            print " = Zieleinkaufspreis: " + str(R_ZKP) + " Euro"
            print "-----------------------"
            LSK = float(raw_input (" - Lieferantenskonto (%) "))
            BKP = float(Decimal(ZKP-ZKP*LSK/100))
            R_BKP = round(BKP, 3)
            print " = Bareinkaufspreis: " + str(R_BKP) + " Euro"
            print "-----------------------"
            BZK= float(raw_input("+ Bezugskosten "))
            BZP = float(Decimal(BZK+BKP))
            R_BZP = round(BZP, 3)
            print " = Einstandspreis (Bezugspreis) " + str(R_BZP) + " Euro"
            print "-----------------------"
            GMK = float(raw_input(" + Gemeinkosten / Handlungskosten (%): "))
            SKP = float(Decimal(BZP+(GMK*BZP)/100))
            R_SKP = round(SKP, 3)
            print " = Selbstkosten: " + str(R_SKP) + " Euro"
            print "======================="
            print ""
            LVKP_brutto = float(raw_input(" Listenverkaufspreis (brutto): "))
            UST = float(raw_input(" - Umsatzsteuer (%): "))
            LVKP_netto = float((LVKP_brutto/(100+UST))*100)
            R_LVKP_netto = round (LVKP_netto, 2)
            print " = Listenverkaufspreis (netto): " + str(R_LVKP_netto) + " Euro"
            print "-----------------------"
            KR = float(raw_input(" + Kundenrabatt: "))
            ZVK = float(Decimal(LVKP_netto/100*(100-KR)))
            R_ZVK = round(ZVK, 2)
            print " = Zielverkaufspreis " + str(R_ZVK)
            print "-----------------------"
            KSK = float(raw_input(" + Kundenskonto: "))
            BVKP = float(Decimal(ZVK/100*(100-KSK)))
            R_BVKP = round(BVKP, 2)
            print " = Barverkaufspreis: " + str(R_BVKP)
            print "-----------------------"
            GZS = float(Decimal(R_SKP-R_BVKP))
            R_GZS = round(GZS, 2)
            GZS_in_Prozent = float(Decimal((R_GZS*100)/R_SKP))
            R_GZS_in_Prozent = round(GZS_in_Prozent, 2)
            print " + Gewinnzuschlag: " + str(R_GZS) + " Euro " + "(" + str(R_GZS_in_Prozent) + "%)"
            print "======================="
                
        def AK(self): # Absatzkalkulation
            print ""
            print """ HINWEIS: Dieses Feature ist noch in Arbeit. Bei der naechsten
                Aktualisierung wird das von Ihnen gewuenschte Feature freigeschalten."""
        
Ich wollte die Methoden in die Klasse unterbringen. Vorher hatte ich es ohne Klasse, sondern nur als Funktionen laufen. Da hat es auch funktioniert. Also, die Formeln für die Berechnungen sind richtig. Jedoch wird nicht mal die start(self)-Methode gestartet, in welcher der Anwender gefragt wird, welches Feature es starten möchte. Bestimmt habe ich was ganz elementares übersehen. Kann mir jemand weiterhelfen?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: wenn Deine Version ohne Klasse funktioniert hat, dann bleib dabei. Für das Programm braucht man keine Klasse und so wie Du das geschrieben hast, ist das auch keine Klasse. Es gäbe zu viel dazu zu schreiben, was Du alles falsch gemacht hast. Am besten lernst Du den Umgang mit Klassen mit einem guten Tutorial.
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Noch paar Tipps: Das erste, was mir auffällt, ist, dass du format benutzen willst:

Code: Alles auswählen

"Willkommen bei {}".format(produkt_name)
Edit: Mach dir nen Triple-Quote-String als Vorlage für den Begrüßungstext. Und formatier da alles mit format rein. Dann brauchst du auch nicht hundert print-s.

Da ist auch schon das Nächste. Es heißt produkt_name. Zumindest sollte es das, standard-konform-er-weise. Steht jdfalls im PEP8. Da stehen auch noch mehr Stiltipps drin.

Den Rest überlasse ich jez mal Blackjack und Hyperion :D .
Zuletzt geändert von Üpsilon am Montag 23. Februar 2015, 21:23, insgesamt 1-mal geändert.
PS: Die angebotene Summe ist beachtlich.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Sirius3,

habe ich grundlegend alles falsch gemacht? Also, das haut mich jetzt um. Dachte, ich käme endlich mal einen Schritt vorwärts. Was habe ich denn alles falsch gemacht? Und das mit der Klasse, ich wollte einfach nur den Umgang mit der Klasse lernen. Das die Klasse in meinem Programm überzogen wäre, ist mir durchaus bekannt, aber irgendwo muss man ja anfangen mit der Klasse zu arbeiten, mhmh?
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

(Ich bin zwar nicht angesprochen, aber antworte trotzdem.)

Objekte sind dazu da, Daten zu gruppieren (=Attribute) und auf Knopfdruck zu verändern (=Methoden).

Und hier ist halt nix, was man gruppieren oder modifizieren muss. Deswegen ist die Klasse sinnlos.

Vlt stellt ich demnächst mal n Beispiel mit ner imho sinnvollen Klasse hier rein.

Lg Y.
PS: Die angebotene Summe ist beachtlich.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich bin gespannt und neugierig zu gleich. Ich hatte nur gehofft, dass ich in meinem Programm gleich mal lernen kann, wie man mit Klassen umgeht - ob es nun sinnvoll oder weniger sinnvoll sei, habe ich erstmal nicht berücksichtigt. Schließlich wollte ich nicht gleich ein monströses Programm schreiben, nur damit die Bedeutung einer Klasse zum Vorschein kommt :-)
BlackJack

@Sophus: Man kann doch den Umgang mit Klassen nicht lernen in dem man sie einfach so ”einsetzt” denn zum Umgang mit Klassen gehört das man sie *richtig* einsetzt und auch das man *keine* einsetzt, wenn die gar nicht gebraucht wird. Einen Haufen Funktionen in eine Klasse zu stecken die da nicht hineingehören ist genau so sinnfrei wie bei jeder Rechnung Grundsätzlich noch mal ein ``* 1 + 0`` anzufügen um den Umgang mit ``*`` und ``+`` zu lernen. Es erhöht einfach nur unnötig die Komplexität ohne irgendeinen Vorteil oder Zusatznutzen. Und Leser fragen sich was das soll und sind verwirrt.

Die Version mit den Funktionen benutzt auch nicht mal wirklich Funktionen. Die können Argumente und Rückgabewerte haben und man sollte keinen Quelltext wiederholt schreiben oder kopieren. Genau dafür sind ja Funktionen da, das man Sachen die mehrfach gebraucht werden, nur einmal schreiben muss und dann von verschiedenen Stellen im Programm aufrufen kann.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben: [...] und man sollte keinen Quelltext wiederholt schreiben oder kopieren. Genau dafür sind ja Funktionen da, das man Sachen die mehrfach gebraucht werden, nur einmal schreiben muss und dann von verschiedenen Stellen im Programm aufrufen kann.
Aber bei unterschiedlichen Rechnungen werden die Formeln unterschiedlich angewandt. Eine Funktion kann ich immer und immer wieder verwenden, wenn die Formel gleich bliebe, richtig? Ist hier aber nicht. Demnach bin ich ja gezwungen für jede Kalkulations-Art eine neue Funktion zu schreiben. Zumindest würde ich so denken.
BlackJack

@Sophus: In diesen Funktionen gibt es aber Sachen die in mehreren Funktionen gleich sind.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ja, das stimmt. An einigen Stellen wiederholt sich einiges. Also steh ich wieder weit am Anfang :-)
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute,

da einige von euch, unter anderem BlackJack mich auf den Umgang mit den Funktionen hingewiesen haben, habe ich meine Funktionen erweitert und ausgelagert:

Hauptprogramm: Kalkulation.py

Code: Alles auswählen

# -*- coding: utf-8 -*-
import sys
import Kalkulationsformeln

# Informationen zum Programm
produkt_name = "Kalkulationsschema fuer den Einzelhandel"
copy_right = "©"
Autor = "Sophus"
Jahr = "2014"
Version = "Built 0.1"
DankSagung = "Mitgliedern des deutschen Python-Forum"
URL_Forum ="http://www.python-forum.de/"
Feature1 = "Beschaffungskalkulation(Vorwaerts)"
Feature2 = "Beschaffungskalkulation(Rueckwaerts)"
Feature3 = "Differenzkalkulation"
Feature4 = "Absatzkalkulation"

print "================================ Hilfe ================================="
print " Tastenkuerzel: - E (Programm beenden)"
print ""
print "================================ Info =================================="
print " Willkommen bei " + produkt_name + "'" + " ( " + Version + " )."
print " Dieses Programm wurde von " + copy_right + " " + Autor + "(" + Jahr + ") geschrieben."
print ""
print "================================ Danksagung ============================"
print " An dieser Stelle moechte ich mich bei den "
print " "+ DankSagung + " bedanken."
print " URL: " + URL_Forum
print ""
print "================================ Menu ==================================" 
print " Folgende Features sind enthalten:"
print "                     (1)" + Feature1
print "                     (2)" + Feature2
print "                     (3)" + Feature3
print "                     (4)" + Feature4
print ""
print "================================ Programm ==============================" 
print ""

def BKV():# Beschaffungskalkulation(Vorwaerts)
    print ""
    print " Die " + Feature1 + " wurde gestartet."
    print ""
    LP = float(raw_input(" Listenpreis: "))
    LR = float(raw_input(" - Lieferantenrabatt (%): "))
    ZKP = Kalkulationsformeln.Zieleinkaufspreis(LP, LR) # Aufruf der Funktion mit Rückgabewert
    print " = Zieleinkaufspreis: ", str(ZKP) + " Euro"
    print "-----------------------"
    LSK = float(raw_input (" - Lieferantenskonto (%) "))
    varZKP = ZKP
    BKP = Kalkulationsformeln.Bareinkaufspreis(LSK, varZKP) # Aufruf der Funktion mit Rückgabewert
    print " = Bareinkaufspreis: " + str(BKP) + " Euro"
    print "-----------------------"
    BZK= float(raw_input("+ Bezugskosten "))
    varBKP = BKP
    BZP = Kalkulationsformeln.Bezugskosten(BZK, varBKP) # Aufruf der Funktion mit Rückgabewert
    print " = Einstandspreis (Bezugspreis) " + str(BZP) + " Euro"
    print "-----------------------"
    GMK = float(raw_input(" + Gemeinkosten / Handlungskosten (%): "))
    varBZP = BZP
    SKP = Kalkulationsformeln.Selbstkosten(GMK, varBZP) # Aufruf der Funktion mit Rückgabewert
    print " = Selbstkosten: " + str(SKP) + " Euro"
    print "-----------------------"
    GZS = float(raw_input(" + Gewinnzuschlag (%): "))
    BVKP = Kalkulationsformeln.Selbstkosten(GZS, SKP) # Aufruf der Funktion mit Rückgabewert
    print " = Barverkaufspreis: " + str(BVKP) + " Euro"
    print "-----------------------"
    KSK = float(raw_input(" + Kundenskonto (%): "))
    VP = float(raw_input(" + Vertreterprovision (%): "))
    varBVKP = BVKP
    ZVKP = Kalkulationsformeln.Zielverkaufspreis(KSK, VP, varBVKP) # Aufruf der Funktion mit Rückgabewert
    print " = Zielverkaufspreis: " +str(ZVKP) + " Euro"
    print "-----------------------"
    KR = float(raw_input(" + Kundenrabatt: "))
    varZVKP = ZVKP
    LVKP_n = Kalkulationsformeln.Kundenrabatt(KR, varZVKP) # Aufruf der Funktion mit Rückgabewert
    print " = Listenverkaufspreis (netto): " + str(LVKP_n) + " Euro"
    print "-----------------------"
    UST = float(raw_input(" + Umsatzsteuer (%): "))
    varLVKP = LVKP_n
    LVKP_b = Kalkulationsformeln.Umsatzsteuer(UST, varLVKP) # Aufruf der Funktion mit Rückgabewert
    print " = Listenverkaufspreis (brutto): " + str(LVKP_b) + " Euro"
    print "======================="

def BKVR(): # Beschaffungskalkulation(Rueckwaerts)
    print ""
    print """ HINWEIS: Dieses Feature ist noch in Arbeit. Bei der naechsten
                    Aktualisierung wird das von Ihnen gewuenschte Feature freigeschalten."""

def DK(): # Differenzkalkulation
        print ""
    print """ HINWEIS: Dieses Feature ist noch in Arbeit. Bei der naechsten
                    Aktualisierung wird das von Ihnen gewuenschte Feature freigeschalten."""

# Anwender soll sich einFeatur (Methode) aussuchen
#try:
VarDict ={"1":Feature1, "2":Feature2, "3": Feature3, "4": Feature4}
                    
Eingabe = raw_input(""" Waehlen Sie ein Feature aus dem Menu, indem sie die entsprechende
                             Zahl eingeben! """)

MyString = ' Sie haben sich fuer das folgende Feature entschieden: '
print MyString + VarDict[Eingabe]

if Eingabe == "1":
    BKV()   # Beschaffungskalkulation(Vorwaerts)-Methode aufrufen
if Eingabe == "2":
    BKVR()  # Beschaffungskalkulation(Rueckwaerts)-Methode aufrufen
if Eingabe == "3":
    DK()    # Differenzkalkulation-Methode aufrufen    
if Eingabe == "4":
    AK()    # Absatzkalkulation-Methode aufrufen

Modul: Kalkulationsformeln.py (Sammlung von Funktionen und Formeln)

Code: Alles auswählen

# -*- coding: utf-8 -*-
from __future__ import division
from decimal import Decimal

def Zieleinkaufspreis(Listpreis, LiefRab):
    ZKP = Decimal(Listpreis-Listpreis*LiefRab/100)
    ZKP_r = round(ZKP, 2)
    return ZKP_r
    
def Bareinkaufspreis(LiefSkon, varZKP):
    BKP = Decimal(varZKP-varZKP*LiefSkon/100)
    BKP_r = round(BKP, 2)
    return BKP_r

def Bezugskosten(BeZuKo, varBKP):   
    BZP = Decimal(BeZuKo+varBKP)
    BZP_r = round(BZP, 2)
    return BZP_r

def Selbstkosten(GeMeKo, varBZP):
    SKP = Decimal(varBZP+(GeMeKo*varBZP)/100)
    SKP_r = round(SKP, 2)
    return SKP_r

def Gewinnzuschlag(GeWiZuSch, varSKP):
    BVKP = Decimal(varSKP+(varSKP*GeWiZuSch)/100)
    BVKP_r = round(BVKP, 2)
    return BVKP_r

def Zielverkaufspreis(KuSk, VePr, varBVKP):
    KSK_Zwsichenschritt = Decimal(varBVKP*KuSk/(100-KuSk-VePr))
    R_KSK_Zwsichenschritt = round(KSK_Zwsichenschritt, 2)
    VP_Zwischenschritt = Decimal(varBVKP*VePr/(100-KuSk-VePr))
    R_VP_Zwischenschritt = round(VP_Zwischenschritt, 2)
    ZVP = Decimal(varBVKP+(R_KSK_Zwsichenschritt+R_VP_Zwischenschritt))
    ZVP_r = round(ZVP, 2)
    return ZVP_r

def Kundenrabatt(KuRa, varZVP):
    LVKP_netto = Decimal(varZVP/(100-KuRa)*100)
    LVKP_netto_r = round(LVKP_netto, 2)
    return LVKP_netto_r

def Umsatzsteuer(UmSaSt, varLVKP_n):
    LVKP_brutto = Decimal(varLVKP_n+varLVKP_n/100*UmSaSt)
    LVKP_brutto_r = round (LVKP_brutto, 2)
    return LVKP_brutto_r
Soweit funktioniert auch alles super. Eine Frage vorweg: Habt ihr einige Kritikpunkte bzw. Anregungen für Verbesserung meines Codes? Und dann habe ich noch eine Frage: Wenn ich in meiner Berechnung folgendes Zeichen (,) als Komma verwendet, wirft mein Programm Fehlermeldungen heraus. Ich weiß, dass hierbei (.) als Kommata gelten. Aber wie lässt sich solch ein Fehler anfangen bzw. sowas vorbeugen?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Sophus hat geschrieben:Aber wie lässt sich solch ein Fehler anfangen bzw. sowas vorbeugen?
Ich denke, hier darf man auch mal etwas Magie anwenden:

Code: Alles auswählen

def float_input(prompt):
    f = raw_input(prompt).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        raise ValueError('Please give me a decimal!')
Dabei wird ein eventuell eingegebenes Komma durch den benötigten Punkt ersetzt. Wenn allerdings etwas eingegeben wird, was einfach nicht in eine Zahl umgewandelt werden kann, wird ein `ValueError` geworfen, der dann an anderer Stelle nochmal abgefangen werden kann.

Deine Funktionen ähneln sich doch sehr. Ohne das jetzt im Detail getestet zu haben, könnte ich mir vorstellen, etwas in dieser Art zu machen:

Code: Alles auswählen

import operator

scheme = [
    ('- Lieferantenrabatt in %: ', True, operator.sub),
    ('- Lieferantenskonto in %: ', True, operator.sub),
    ('+ Bezugskosten          : ', False, operator.add)
]

def percentage(base, percent):
    return (base/100.0)*percent

def float_input(prompt):
    f = raw_input(prompt).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        raise ValueError('Please give me a decimal!')

def run(catalog_price):
    base = catalog_price
    for name, is_percent, operator_ in scheme:
        if is_percent:
            base = operator_(base, percentage(base, float_input(name)))
        else:
            base = operator_(base, float_input(name))
    return base
Deine step-by-step Eingabe<>Ausgabe müsste man natürlich noch einbauen. Aber eventuell lässt sich in dieser Richtung weitermachen...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das "Hauptprogramm" ist auch noch deutlich zu unpythonisch.

Namen nummeriert man nicht! ``Feature1`` usw. zeigt, dass Du da eine Liste o.ä. nutzen willst. (Später packst Du die Strings ja sogar in ein Dictionary!)

Für das Menü (und den Lerneffekt) empfehle ich mal vollkommen unbefangen folgendes: Tutorial für Textmenüs 8)

Du solltest *keinen* Code auf Modulebene stehen haben. Nutze den folgenden Trick:

Code: Alles auswählen

def main():
    # hier steht dann Dein Einstiegscode, der beim Starten ausgeführt werden soll

if __name__ == "__main__":
    main()
Die ganzen Metainformationen verpackt man besser in die dafür vorgesehenen Strukturen. Zum einen sind das Docstrings, die nach dem Sphinx Standard geschrieben sind, zum anderen spezielle Attribute von Modulen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Sophus: `Decimal` ist total überflüssig. Du rufst am Ende von den Rechenoperationen `round()` auf, womit man wieder bei `float()` ist und ich sehe bei den Operationen nichts wo Decimal tatsächlich einen Unterschied machen würde, solange die Eingangswerte nicht so gross werden dass sie zu Ungenauigkeiten führen. Solange man damit also nicht den Rüstungsetat für den nächsten Krieg den der Friedensnobelpreisträger aus den USA vom Zaun brechen könnte, berechnen will, sollte es da keine Probleme geben. :-)
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

mutetella hat geschrieben:
Sophus hat geschrieben:Aber wie lässt sich solch ein Fehler anfangen bzw. sowas vorbeugen?
Ich denke, hier darf man auch mal etwas Magie anwenden:

Code: Alles auswählen

def float_input(prompt):
    f = raw_input(prompt).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        raise ValueError('Please give me a decimal!')
Dabei wird ein eventuell eingegebenes Komma durch den benötigten Punkt ersetzt. Wenn allerdings etwas eingegeben wird, was einfach nicht in eine Zahl umgewandelt werden kann, wird ein `ValueError` geworfen, der dann an anderer Stelle nochmal abgefangen werden kann.
Hallo mutetella, ich habe mir eben die Mühe gemacht, und deine Replace-Funktion getestet, leider ohne Erfolg. hier mein Code:

Code: Alles auswählen

def test_func():
    KSK = float(raw_input("Eine Zahl mit Komma bitte: "))
    f = raw_input(KSK).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        print "ERROR"
        raise ValueError('Please give me a decimal!')

test_func()
Ich habe hier die Zahl 100,00 eingegeben, und als Fehlermeldung spuckt er mir dann folgendes aus:
Traceback (most recent call last):
File "D:\Dan\Python\Übung\Calc\Replace.py", line 10, in <module>
test_func()
File "D:\Dan\Python\Übung\Calc\Replace.py", line 2, in test_func
KSK = float(raw_input("Eine Zahl mit Komma bitte: "))
ValueError: invalid literal for float(): 100,00
mutetella hat geschrieben: Deine Funktionen ähneln sich doch sehr. Ohne das jetzt im Detail getestet zu haben, könnte ich mir vorstellen, etwas in dieser Art zu machen:

Code: Alles auswählen

import operator

scheme = [
    ('- Lieferantenrabatt in %: ', True, operator.sub),
    ('- Lieferantenskonto in %: ', True, operator.sub),
    ('+ Bezugskosten          : ', False, operator.add)
]

def percentage(base, percent):
    return (base/100.0)*percent

def float_input(prompt):
    f = raw_input(prompt).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        raise ValueError('Please give me a decimal!')

def run(catalog_price):
    base = catalog_price
    for name, is_percent, operator_ in scheme:
        if is_percent:
            base = operator_(base, percentage(base, float_input(name)))
        else:
            base = operator_(base, float_input(name))
    return base
Deine step-by-step Eingabe<>Ausgabe müsste man natürlich noch einbauen. Aber eventuell lässt sich in dieser Richtung weitermachen...

mutetella
Deine Anregung werde ich mir noch einmal durchdenken. Das Problem bei Kalkulationen ist, dass sich immer Kleinigkeiten ändern. Aber ich bin auch kein Mathe-Genie, daher habe ich es für mich insofern vereinfacht, dass ich für jedes "Thema" eine Funktion erstellt habe. Somit wär ich auf der sicheren Seite :-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Sophus hat geschrieben:Hallo mutetella, ich habe mir eben die Mühe gemacht, und deine Replace-Funktion getestet, leider ohne Erfolg. hier mein Code:
Dann vergleiche noch einmal deinen Code mit dem von mutetella. Kleiner Tipp: Achte mal auf den Namen der Funktion von mutetella und die Reihenfolge der Operationen: Einlesen, Ersetzen, Umwandeln.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hyperion hat geschrieben:Das "Hauptprogramm" ist auch noch deutlich zu unpythonisch.

Namen nummeriert man nicht! ``Feature1`` usw. zeigt, dass Du da eine Liste o.ä. nutzen willst. (Später packst Du die Strings ja sogar in ein Dictionary!)

Für das Menü (und den Lerneffekt) empfehle ich mal vollkommen unbefangen folgendes: Tutorial für Textmenüs 8)

Du solltest *keinen* Code auf Modulebene stehen haben. Nutze den folgenden Trick:

Code: Alles auswählen

def main():
    # hier steht dann Dein Einstiegscode, der beim Starten ausgeführt werden soll

if __name__ == "__main__":
    main()
Die ganzen Metainformationen verpackt man besser in die dafür vorgesehenen Strukturen. Zum einen sind das Docstrings, die nach dem Sphinx Standard geschrieben sind, zum anderen spezielle Attribute von Modulen.
Hallo Hyperion, ich habe eben deinen Rat gefolgt, und dies versucht wie folgt umzusetzen. Ich will noch anmerken, dass ich mich an diesen Tipp https://github.com/Lysander/snippets/bl ... UTORIAL.md gehalten habe, was das Erstellen von Text-Menue betrifft.

Code: Alles auswählen

# Anwender soll sich einFeatur (Methode) aussuchen
def handle_menu(menu):
    while True:
        for index, item in enumerate(menu, 1):
            print("{}  {}".format(index, item[0]))
        choice = int(input("Ihre Wahl? ")) - 1
        if 0 <= choice < len(menu):
            menu[choice][1]()
        else:
            print("Bitte nur Zahlen im Bereich 1 - {} eingeben".format(
                                                                    len(menu)))

    handle_menu(menu)

def main():
    menu = [
        ["Beschaffungskalkulation(Vorwaerts)", BKV],
        ["Beschaffungskalkulation(Rueckwaerts)", BKVR],
        ["Differenzkalkulation", DK],
        ["Absatzkalkulation", AK],
        ["Beenden", quit]
    ]
    handle_menu(menu) # Aufruf der Funktion handle_menu() mit dem Argument menu, 
                                 # welcher hier in der Funktion als Objekt (oder doch Variable?) dient.
Der Code funktioniert zwar, aber nicht was funktioniert muss mit der Richtigkeit gleichbedeutend sein, richtig? :-) Ich wollte nur wissen, ob ich hier richtig gehandelt habe oder etwas untypisch oder gar falsch ist?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

EyDu hat geschrieben:
Sophus hat geschrieben:Hallo mutetella, ich habe mir eben die Mühe gemacht, und deine Replace-Funktion getestet, leider ohne Erfolg. hier mein Code:
Dann vergleiche noch einmal deinen Code mit dem von mutetella. Kleiner Tipp: Achte mal auf den Namen der Funktion von mutetella und die Reihenfolge der Operationen: Einlesen, Ersetzen, Umwandeln.
Hallo EyDu,

ich habe nochmal überprüft, es kommt natürlich keine Fehlermeldung, aber wirklich richtig arbeiten tut die Funktion auch nicht. Hier mein veränderter Code:

Code: Alles auswählen

def float_input(prompt):
    #KSK = float(raw_input("Eine Zahl mit Komma bitte: "))
    f = raw_input(prompt).replace(',', '.')
    try:
        return float(f)
    except ValueError:
        raise ValueError('Please give me a decimal!')

def main():
    Zahl = '100,00'
    float_input(Zahl)


if __name__ == "__main__":
    main()
Übergebe ich der Funktion float_input() die Variable (hier 100,00), so gibt die Funktion float_input() als Ergebis 100,00 aus. Es wird nicht ersetzt. Irgendwas mache ich falsch, oder?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

In "Zahl" wird nichts auf magische Weise ersetzt, Schon gar nicht vor dem Aufruf der Umwandlungsfunktion. Das wäre ja total verrücktes Verhalten. Versuche mal zu verstehen was "float_input" macht. Zerleg sie in Einzelschritte, lass dir die Zwischenergebnisse dazu ausgeben und zusätzlich dazu den Typ.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

EyDu hat geschrieben:In "Zahl" wird nichts auf magische Weise ersetzt, Schon gar nicht vor dem Aufruf der Umwandlungsfunktion. Das wäre ja total verrücktes Verhalten. Versuche mal zu verstehen was "float_input" macht. Zerleg sie in Einzelschritte, lass dir die Zwischenergebnisse dazu ausgeben und zusätzlich dazu den Typ.
Ich weiß zwar nicht, was du mit "[...]vor dem Aufruf der Umwandlungsfunktion", meinst, denn die Funktion main() wird hierbei zuerst aufgerufen, udn später die Funktion float_input, soweit ich das verstanden habe. Aber ich zerlege mal den Code mit Kommentaren, so wie ich sie verstehe:

Code: Alles auswählen

def float_input(prompt): # Funktion für die Umwandlung von Komma in Punkt

    f = raw_input(prompt).replace(',', '.') # f wird hier zum Objekt gemacht, damit man damit später arbeiten kann.
                                            # In der Eingabe (promt) wird nach bestimmten Zeichen durchsucht.
                                            # Wurde ein Komma gefunden, soll es durch einen Punkt ersetzt werden.
    try: # Ist eine Art Ausnahmebehandlung 
        return float(f) # Der Wert f soll als Float an die Funktion zurückgegeben werden
    except ValueError: # Bei einem Fehler wird ValueError rausgeworfen.
        raise ValueError('Please give me a decimal!')

def main(): # Damit kein Code auf der Modulebene steht. Sobald das Modul als Hauptprogramm gestartet wird, wird diese Funktion zuerst aufgerufen.
    
    Zahl = '100,00' # Die Variable mit einer Zahl füllen
    float_input(Zahl) # Funktion aufrufen, und die gefüllte Variable als ein Argument an die Funktion übergeben

if __name__ == "__main__":
    main()

Antworten