Kaloriengrundumsatz berechnen

Code-Stücke können hier veröffentlicht werden.
Antworten
Citral
User
Beiträge: 12
Registriert: Dienstag 7. Juni 2016, 04:27
Kontaktdaten:

Hey,
einer meiner ersten OOP-Projekte, wenn es denn OOP ist, bin mir da selbst nicht sicher :mrgreen:

Code: Alles auswählen

#!/usr/bin/env python3.5

class Object():
    def __init__(self, gewicht, groesse, alter):
        self.Gewicht = gewicht
        self.Groesse = groesse
        self.Alter = alter
        print('BMI: ' + str(self.BMI()))

    def BMI(self):
        groesse = self.Groesse / 100
        BMI = int(self.Gewicht / (groesse * groesse))
        return BMI

    def Frau(self):
        if self.BMI() >= 30:
            KCAL = int(2.4 * self.Gewicht  + 9 * self.Groesse - 4.7 * self.Alter - 65)
            return KCAL
        elif self.BMI() < 30:
            KCAL = int(655 + 9.6 * self.Gewicht + 1.8 * self.Groesse - 4.7 * self.Alter)
            return KCAL
        else:
            return False

    def Mann(self):
        if self.BMI() >= 30:
            KCAL = int(3.4 * self.Gewicht + 15.3 * self.Groesse - 6.8 * self.Alter - 961)
            return KCAL
        elif self.BMI() < 30:
            KCAL = int(66.5 + 13.7 * self.Gewicht + 5 * self.Groesse - 6.8 * self.Alter)
            return KCAL
        else:
            return False

########TestBereich########
print(Object(60, 175, 25).Frau())
print(Object(90, 180, 30).Frau())
print(Object(70, 188, 25).Mann())
print(Object(111, 185, 30).Mann())
Bild

Freu mich natürlich über Feedback und Verbesserungsvorschläge
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mit OOP hat das nichts zu tun. Die Tatsache dass dir selbst kein besserer Name als Object für die Klasse eingefallen ist, hätte dir dass selbst schon mehr als deutlich zeigen sollen.

Ansonsten hat Python einen Style Guide, PEP 8, der eine Reihe von Konventionen festlegt. Die Schreibweise fast aller Namen verstößt dagegen.

Wo wir bei Namen sind: Funktionen und Methoden tuen etwas. BMI, Mann und Frau sind Nomen und beschreiben keine Tätigkeit, man tut nicht BMI, Mann oder Frau. Verwende für Funktionen und Methoden Verben oder etwas was diesem Nahe kommt wie get_bmi oder get_female_bmr (basal metabolic rate).

Wenn Fehler auftreten wirft man in Python eine Exception. Man muss und sollte nicht Fehler über Rückgabewerte signalisieren.

Wenn du irgendwelche konstanten Strings oder Zahlen hast die eine bestimmte Bedeutung haben, wie die ganzen Zahlen in den Mann und Frau Methoden, solltest du diesen Namen geben. Das macht auch dann Sinn wenn du sie nicht auf Modulebene definieren möchtest.

Wenn du irgendwelche nicht-trivialen Formeln oder Algorithmen verwendest, solltest du diese mit einem Kommentare erklären oder zumindest erklären wie die heissen und eine Quelle (Wikipedia Artikel, Textbuch, Paper, Blog Post, ...) nennen.

In Mann und Frau rufst du BMI zweimal auf, dass ist einmal mehr als notwendig. Du kannst dir dass Ergebnis merken, tust du für KCAL (wieder ein schlechter Name, sind dass die Kalorien die ein Stück Kuchen hat?) doch auch und da hättest du es dir auch sparen können.

Die Print Statements solltest du entfernen, wenn du willst dass dein Code ernsthaft genutzt werden kann. Wenn du deinen Code Testen willst, schreib unit tests. Die Standard Library bietet für letzteres doctest (nicht so toll aber hier ausreichend) und unittest (ganz in Ordnung). Wenn du etwas tiefer in den Bereich einsteigen willst, solltest du einen Blick auf pytest werfen.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Citral: das was Du da geschrieben hast, könnte man genauso gut als Funktion schreiben. Das Problem, warum das keine Klasse ist, liegt einfach daran, dass man nur eine Sache mit der Klasse machen kann. Das Geschlecht liegt ja normalerweise auch schon fest, wenn man das Gewicht und Alter der Person kennt. Die Formeln in "Frau" und "Mann" sind alle gleich, so dass man die Faktor herausziehen und die Formel nur einmal schreiben muß. Wenn eine Bedingung <= und eine > heißt, dann kann es keinen else-Zweig mehr geben, weil die zweite Bedingung das Gegenteil der ersten und damit dies der else-Zweig wäre. Das "False" ist schlecht, weil eine Funktion genau eine Art von Ergebnis liefern; Fehler werden über Exceptions zurückgemeldet. Da False auch 0 heißen kann, könnte es leicht passieren, dass im weiteren mit falschen Werten gerechnet wird, statt dass der Fehler auftritt (der ja zum Glück nicht auftreten kann).

Code: Alles auswählen

#!/usr/bin/env python3.5
from collections import namedtuple

CaloryFactors = namedtuple("CaloryFactors", "weight, height, age, const")

WEIGHT_HEIGHT_AGE_FACTORS = {
    ("woman", "large_BMI"): CaloryFactors(2.4, 9, -4.7, -65),
    ("woman", "small_BMI"): CaloryFactors(9.6, 1.8, -4.7, 665),
    ("man", "large_BMI"): CaloryFactors(3.4, 15.3, -6.8, -961),
    ("man", "small_BMI"): CaloryFactors(13.7, 5, -6.8, 66.5),
}

def calculate_bmi(weight, height):
    return weight / (height/100) ** 2
 
def calculate_daily_calories(weight, height, age, sex):
    factors = WEIGHT_HEIGHT_AGE_FACTORS[sex, "small_BMI" if calculate_bmi(weight, height) < 30 else "large_BMI"]
    return factors.weight * weight + factors.height * height + factors.age * age + factors.const
        
print(calculate_daily_calories(60, 175, 25, "woman"))
print(calculate_daily_calories(90, 180, 30, "woman"))
print(calculate_daily_calories(70, 188, 25, "man"))
print(calculate_daily_calories(111, 185, 30, "man"))
Antworten