Hilfestellung für einen Anfänger

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
Noofuu
User
Beiträge: 7
Registriert: Dienstag 11. Juni 2019, 17:46

Hallo ,

Ich habe hier ein kleines "Programm" geschrieben so als Anfänger.
Nun möchte ich das ganze aber etwas anders gestalten , nur weiß ich nicht genau womit ich da Arbeiten muss.

Hier erstmal der Code:

Code: Alles auswählen

print("Persönlicher kcal Rechner",("\n"))

Name = input("Geben sie bitte ihren Namen ein: ")
print("Herzlich Willkommen zu ihrem Persönlichen kcal-Rechner:", Name)   
print("\n")

tagesbedarf = eval(input("Dein Tagesbedarf kcal: "))
print("\n")

Kartoffel = eval(input("Wieviel Gramm Kartoffeln?: "))
Thunfisch = eval(input("Wieviel Gramm Thunfisch?: "))
Milch = eval(input("Wieviel Millilieter Milch?:"))
Reis = eval(input("Wieviel Gramm Reis?:"))

K = Kartoffel * 0.7
T = Thunfisch * 1.11
M = Milch * 0.48
R = Reis * 1.26
liste = K + T + M + R


print(M,"kcal", "Milch", ("\n"))
print(K,"kcal", "Kartoffeln", ("\n"))
print(T,"kcal", "Thunfisch", ("\n"))
print(R,"kcal", "Reis", ("\n"))
print(liste,"Gesammte kcal")
print(tagesbedarf - liste, "kcal stehen noch zur Verfügung.")

L = tagesbedarf - liste


if L < 0:
    print("Achte auf deinen Maximalen Tagesbedarf, leider überschritten!")
else:
    print("Achte darauf das du den Tagesbedarf noch aufbrauchst!")
Also ich möchte es lieber so machen, das ich z.B ein Produkt wie z.B Kartoffel Eingeben muss und er dann mit dem Wert Rechnet.
Jetzt kommt ja alles nacheinander , ich hatte aber lieber eine Abfrage wie z.B Was haben sie heute gegessen: Beispiel : Kartoffel < Eingabe.
Dann wie viel Gramm : Beispiel : 200 < Eingabe
Und er Rechnet es aus, soll aber auch gleichzeitig die Berechnung speichern um am Ende alles vom Tagesbedarf abzuziehen.
Ist bestimmt für einen Anfänger noch zu Komplex oder ?
Windows 10 // Linux Manjaro
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum klammerst Du ("\n") immer ein?
`eval` solltest Du nicht benutzen,, wenn Du Zahlen konvertieren willst, benutze `float`.
Variablennamen werden nach Konvention klein geschrieben. Einbuchstabige Namen sind schlecht, weil sie nichts aussagen, also statt K -> energiemenge_kartoffeln.

Für Dein Vorhaben brauchst Du Schleifen und Listen, Wörterbücher wären auch ganz nett. Das Programm hat inzwischen auch eine Größe erreicht, in dem Du es mit Funktionsdefinitionen strukturieren solltest.

Das sind alles Dinge, die als nächstes auf Deiner Lern-Liste für's Programmieren stehen sollten, also nichts zu Komplexes.

Definiere ein Wörterbuch, in dem den Lebensmitteln die Kalorienzahl zugeordnet wird.
Lese in einer Schleife erst das Lebensmittel und die Menge ein, suche aus dem Wörterbuch die Kalorienzahl und berechne die Gesamtenergiemenge.
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Noofuu: Bevor Du irgendetwas anderes machst solltest Du `eval()` loswerden und am besten gleich wieder vergessen, dass es das gibt. Du willst die Eingabe in eine Zahl umwandeln und nicht das der Benutzer beliebige Python-Ausdrücke eingeben kann. Das reisst eine riesige Sicherheitslücke in Programme, und wenn Du anfängst Dich um Fehlerbehandlung zu kümmern, damit das Programm bei Fehleingaben nicht einfach abbricht, dann kann bei `eval()` tatsächlich so gut wie *alles* passieren, weil der Benutzer so gut wie alles machen kann, solange es sich nur als Python-Ausdruck formulieren lässt. Bei `float()` muss man sich nur um einen eventuellen `ValueError` kümmern.

Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Einbuchstabige Namen sind nur in seltenen Fällen sinnvoll. Zum Beispiel bei `x` und `y` für Koordinaten, oder `i` und `j` als Laufvariablen und/oder für Indexzugriffe bei Sequenzen (`list`, `tuple`, …). Das sind Leser aus der Mathematik gewohnt. Aber das `K` für die Kalorien für eine Menge von Kartoffeln steht, ist nicht wirklich selbsterklärend. Namen sind aber genau dafür da: um dem Leser zu vermitteln was der Wert dahinter im Kontext des Programms bedeutet.

Noch schlimmer sind Namen die nicht stimmen, wie zum Beispiel `liste` für eine Zahl zu verwenden.

Warum setzt Du '\n' immer in Klammern? Die machen keinen Sinn. Zudem kann man das Zeilenende in allen Fällen wo Du das als einzelnes Argument an `print()` übergibst, auch einfach am Ende der Zeichenkette schreiben, die als Argument davor übergeben wird. Ebensowenig ist es sinnvoll 'kcal' bei der Ausgabe der Kalorien pro Lebensmittel als eigenes Argument, getrennt vom Lebensmittelnamen zu übergeben.

Man sollte ”magische” Zahlen im Code vermeiden. Für die „kcal pro Einheit Lebensmittel“-Werte würde man Konstanten definieren.

Die Restkalorien berechnet das Programm zweimal – solche Wiederholungen sollte man vermeiden.

Die Auswertung am Ende berücksichtig nicht den Fall, das man den Tagesbedarf exakt getroffen hat. Die Ausgaben die der Benutzer dann bekommt, ist nicht wirklich sinnvoll.

Zwischenstand bis hierher:

Code: Alles auswählen

#!/usr/bin/env python3
from math import isclose

KCAL_PRO_GRAMM_KARTOFFEL = 0.7
KCAL_PRO_GRAMM_THUNFISCH = 1.11
KCAL_PRO_MILLILITER_MILCH = 0.48
KCAL_PRO_GRAMM_REIS = 1.26


def main():
    print('Persönlicher kcal Rechner\n')

    name = input('Geben sie bitte ihren Namen ein: ')
    print('Herzlich Willkommen zu ihrem persönlichen kcal-Rechner:', name)   
    print('\n')

    tagesbedarf = float(input('Dein Tagesbedarf kcal: '))
    print('\n')

    kartoffel = float(input('Wieviel Gramm Kartoffeln?: '))
    thunfisch = float(input('Wieviel Gramm Thunfisch?: '))
    milch = float(input('Wieviel Milliliter Milch?: '))
    reis = float(input('Wieviel Gramm Reis?: '))

    kartoffel_kcal = kartoffel * KCAL_PRO_GRAMM_KARTOFFEL
    thunfisch_kcal = thunfisch * KCAL_PRO_GRAMM_THUNFISCH
    milch_kcal = milch * KCAL_PRO_MILLILITER_MILCH
    reis_kcal = reis * KCAL_PRO_GRAMM_REIS
    gesamt_kcal = kartoffel_kcal + thunfisch_kcal + milch_kcal + reis_kcal
    rest_kcal = tagesbedarf - gesamt_kcal

    print(kartoffel_kcal, 'kcal Kartoffeln\n')
    print(thunfisch_kcal, 'kcal Thunfisch\n')
    print(milch_kcal, 'kcal Milch\n')
    print(reis_kcal, 'kcal Reis\n')
    print(gesamt_kcal, 'Gesammte kcal')
    print(rest_kcal, 'kcal stehen noch zur Verfügung.')

    if rest_kcal < 0:
        print('Achte auf deinen Maximalen Tagesbedarf, leider überschritten!')
    elif isclose(rest_kcal, 0):
        print('Perfekt!  Ab jetzt heute nichts mehr essen.')
    else:
        print('Achte darauf das du den Tagesbedarf noch aufbrauchst!')


if __name__ == "__main__":
    main()
Das was Du da als nächstes vorhast braucht Datenstrukturen. Du musst als erstes die Daten für die einzelnen Lebensmittel hinterlegen, also Name ('Kartoffel', …), Einheit ('Gramm', 'Milliliter', …), und Kalorienverbrauch pro Einheit. Da der Benutzer das Lebensmittel eingeben soll, und Du daraufhin die anderen beiden Werte benötigst, bietet sich ein Wörterbuch (`dict`) an, das den Lebensmittelnamen beispielsweise auf ein Tupel aus Einheit und Kalorien pro Einheit abbildet.

Um die Werte dann zu speichern bietet sich ebenfalls wieder ein Wörterbuch an, das den Lebensmittelnamen auf die Anzahl der aufgenommenen Kalorien abbildet. Eventuell auch ein `collections.defaultdict`, denn wenn der Benutzer zweimal das gleiche Lebensmittel eingibt, will man ja wahrscheinlich die neuen Daten zu den bereits eingegebenen addieren.

Du solltest dann auch Fehleingaben explizit behandeln, damit ein Vertipper nicht dazu führen kann, dass alle bisherigen Eingaben durch den Programmabbruch zunichte gemacht werden.

Und bei der Eingabe des Lebensmittel könntest Du auch überlegen ob es für den Benutzer nicht eventuell einfacher ist, wenn man ihm eine Liste von Möglichkeiten mit Nummer präsentiert, die er dann eingibt, als das er tatsächlich immer den Namen 'Kartoffel' tippen muss.

Sowohl bei der Fehlerbehandlung als auch bei einem Textmenü zur Auswahl sind wir dann beim Thema Funktionen angekommen, denn die sollte man dann schreiben, statt alles linear im Hauptprogramm runter zu hacken, potentiell auch noch mit Codewiederholungen.

Fehlerbehandlung könnte auch ein Schritt vor dem ”flexibilisieren” der Eingabe sein, also das die Zahleneingaben entsprechend abgesichert sind falls der Benutzer keine Zahl eingibt. Und in diesem Programm machen bei den gültigen Eingaben auch nur positive Zahlen Sinn – das könnte man auch bei der Eingabe berücksichtigen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
Noofuu
User
Beiträge: 7
Registriert: Dienstag 11. Juni 2019, 17:46

Danke für die Ausführliche Hilfe , werde mich heute Abend ans Werk machen :)
eval hatte ich erst gelernt, float habe ich in einer zweiten version auch genutzt dort hat der eigentliche weg aber nicht funktioniert (Anfänger halt).

Ich bin ja schon einmal Froh das ich selbst eine idee gefunden habe die ich in ein Programm wandeln will, das fand ich mit am schwersten... ja jetzt lernst du eine Programmiersprache aber was genau willst du damit anfangen.
Windows 10 // Linux Manjaro
enoapex
User
Beiträge: 2
Registriert: Freitag 5. Juli 2019, 11:16

Hallo,

finde den code ganz interessant und spiele damit momentan ein bisschen.
Wie ist es möglich den folgenden code nur auf int zu bregrenzen?

kartoffel = float(input('Wieviel Gramm Kartoffeln?: '))

Mir würde jetzt spintan eine if abfrage einfallen, um zu prüfen ob es sich um ein string handelnt oder nicht.

if kartoffel = ...

Würde mich über ein bisschen unterstützung freuen.

Vielen dank!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du nur int willst, warum benutzt du dann nicht int statt float? Und was genau soll da eine Pruefung auf string nutzen?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Um zu prüfen ob es sich um einen String handelt kannst du

Code: Alles auswählen

if type(x) == str:
    print("x ist ein String")
else:
    print("x ist kein String")
benutzen. Allerdings macht das kein Sinn, da du den input direkt in ein float konvertierst. Es ist also im Moment nicht möglich bei deinem Programm dort an der Stelle einen String einzugeben, da würde das Programm mit einer Fehlermeldung abbrechen. Den input ohne float() auf einen String zu testen macht auch keinen Sinn, da input immer einen String liefert.
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Jankie: Das würde man so nicht machen. Um auf Typen zu testen ist `isinstance()` da. Und das sollte nur sehr selten nötig sein. Wenn man das öfter braucht, dann macht man etwas falsch, also entweder das man objektorientierte Programmierung nicht richtig umsetzt, oder man möchte sich vielleicht `functools.singledispatch()` mal näher anschauen. Oder das externe `decorator.dispatch_on()`.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Wieder was gelernt, habs bisher zwar noch nicht benötigt aber gut zu wissen. Danke.
enoapex
User
Beiträge: 2
Registriert: Freitag 5. Juli 2019, 11:16

Vielen Dank für die Hilfe. Sehr interessante Beiträge!!
Antworten