Localedatenbank zum Speichern von Rezepten und Speisen

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
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ooldman24: Zu dem Code der die Daten aus einer Exceldatei extrahiert: Ich denke das ist nicht nur eine Frage das einfacher zu gestalten, sondern es ist schlicht eine falsche herangehensweise so verdammt viel Code zu haben der durch kopieren und einfügen entstanden ist und die ganzen durchnummerierten, nichtssagenden Namen. Bei dem ganzen Code der da steht, hätte man auch gleich die Daten per Hand kopieren können. Man programmiert ja normalerweise um manuelle Wiederholungen zu vermeiden, nicht um manuell viel Code (und/oder Daten) zu wiederholen. Und das macht man mit Schleifen, Funktionen, und Datenstrukturen.

Aber fangen wir mit der ersten Zeile an. Die macht keinen Sinn, es sei denn Du hast wirklich im Ordner `/Documente/` einen Python-Interpreter mit dem Namen `Python`. Die „she bang“-Zeile sagt unter Unix mit welchem Programm eine Textdatei ausgeführt werden soll. Unter Windows wird die vom System selbst nicht ausgewertet, aber sie ist mindestens für den Leser interessant um zu sehen ob das für Python 2.x oder Python 3.x gedacht ist, und es gibt Programme wie Webserver und den Python-Launcher der mit *.py-Dateien verknüpft ist, die diese Zeile (teilweise) auswerten. Wenn das Python 3.x-Quelltext sein soll, dann ist die übliche Zeile ``#!/usr/bin/env python3``. Und das ist auch unter Windows sinnvoll, damit der Python-Launcher weiss das ein Python 3.x-Interpreter verwendet werden soll.

`Workbook` wird importiert, aber nirgends verwendet.

Namenskonvention in Python ist kleinbuchstaben_mit_unterstrichen für alles ausser Konstanten (KOMPLETT_GROSS) und Klassennamen (MixedCase). Also `speisenplan` oder `speisen_plan` statt `speisenPlan` und `sheetnamen` oder `sheet_namen` statt `sheetNamen`.

Wobei `sheet_namen` irreführend ist, denn hinter dem Namen würde man zum Beispiel eine Liste mit Zeichenketten erwarten, eben Namen von Arbeitsblättern. Es ist aber tatsächlich das Arbeitsblatt mit dem Namen 'Mittag'.

Und dann fangen die vielen Wiederholungen an. An der Stelle sollte man sich die Struktur der Daten anschauen, sich eine Struktur überlegen in der man die Daten hinterher haben möchte, und dann schauen wie man das eine in das andere Überführen kann.

Es geht ja anscheinend um fünf Wochentage, die jeweils immer gleich strukturiert sind, nämlich als drei Spalten für die drei Gerichte in denen fünf Zeilen pro Gericht stehen. Diese Blöcke haben einen Versatz von neun Zeilen vom Anfang und sind im Abstand von sechs Zeilen angeordnet. Das sind die Eckdaten die man im Programm als Zahlenwerte vorgeben kann.

Als Ziel könnte man eine Liste mit einem Eintrag pro Wochentag nehmen, wobei jeder Eintrag aus drei Listen mit den Zellwerten für das jeweilige Gericht bestehen.

`print()` wandelt die Argumente schon von selbst in Zeichenketten um vor der Ausgabe — ein extra `str()`-Aufruf ist da nicht nötig.

Das ganze ist dann auch mit Schleifen immer noch recht umfangreich; IMHO zu umfangreich für *eine* Funktion. Es werden ja auch zwei deutlich unterscheidbare Dinge getan: Die Daten werden eingelesen und sie werden (leicht) formatiert, ausgegeben. Eingabe, Verarbeitung, und Ausgabe sind traditionell Bereiche an denen man ein Programm gut und sinnvoll auftrennen kann. Eine Verarbeitung fällt hier ja erst einmal weg, also haben wir eine Funktion zum einlesen der Daten in eine sinnvoll Struktur, die Ausgabe der Daten, und das Hauptprogramm, das beides verbindet und üblicherweise in einer Funktion steht die `main()` heisst. Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import os

import openpyxl

DAY_NAMES = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag']
MEAL_NAMES = ['I', 'II', 'FF']

FIRST_COLUMN_NUMBER = 1
FIRST_ROW_NUMBER = 9
MEALS_PER_DAY = 3
ROWS_PER_MEAL = 5
ROWS_PER_DAY = 6
assert ROWS_PER_DAY >= ROWS_PER_MEAL


def load_menu(filename):
    sheet = openpyxl.load_workbook(filename)['Mittag']

    days = list()
    for i in range(len(DAY_NAMES)):
        meals = list()
        day_row_number = FIRST_ROW_NUMBER + i * ROWS_PER_DAY
        meal_columns = sheet.iter_cols(
            FIRST_COLUMN_NUMBER,
            FIRST_COLUMN_NUMBER + MEALS_PER_DAY,
            day_row_number,
            day_row_number + ROWS_PER_MEAL
        )
        for column in meal_columns:
            meals.append([cell.value for cell in column])
        days.append(meals)
    
    return days


def print_menu(days):
    for day_name, meals in zip(DAY_NAMES, days):
        for meal_name, meal in zip(MEAL_NAMES, meals):
            print('{} Gericht {}'.format(day_name, meal_name))
            for value in meal:
                print(value)
    

def main():
    days = load_menu('beispiel.xlsx')
    print_menu(days)


if __name__ == '__main__':
    main()
Was hier noch etwas unschön ist, sind die ”parallelen” Listen mit Werten die Zusammengehören, also die Wochentagnamen und die Daten für den jeweiligen Wochentag, und das gleiche noch einmal mit den Gerichtnamen. Da könnte man überlegen die mit in die Datenstruktur zu stecken und sich beispielsweise `collections.namedtupel` zu erstellen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Ooldman24
User
Beiträge: 16
Registriert: Samstag 11. August 2018, 14:09

Hey __Blackjack__

Vielen dank für deinen Postund sorry für meine späte Antwort. Ich möchte bevor ich weiter an dem Programm schreibe, deinen Code für mich analysieren und vor allem verstehen. Das was du geschrieben hast ist natürlich völlig richtig.

Ich melde mich die Tage wieder, bin z.Z relativ eingespannt.

Vielen lieben Dank für deine Mühe!
Antworten