Vorstellung, erster Beitrag und Frage

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.
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Dann bleibt aber der "Umweg" über datetime.datetime richtig?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja.
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Mist, hänge schon wieder fest in meinem Buch.

Code: Alles auswählen

import shelve
speicher = shelve.open ('meineDaten')
spieler_endrunde = ["Heinz", "Kai", "Heike"]
speicher["im Finale"] = spieler_endrunde
speicher.close
Soll eigentlich eine Datei öffnen. Macht aber nur:


> %Run shelve.py
Traceback (most recent call last):
File "/home/pi/Python/Klassen/_das Modul shelve/shelve.py", line 5, in <module>
import shelve
File "/home/pi/Python/Klassen/_das Modul shelve/shelve.py", line 6, in <module>
speicher = shelve.open ('meineDaten')
AttributeError: partially initialized module 'shelve' has no attribute 'open' (most likely due to a circular import)
>>>

Was'n da schon wieder los?
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

shelve.py, line 6
Your program tries to call method open of an object of type 'shelve', but this type doesn't have such method.

Heißt doch, die Methode gibt es da nicht, oder?

Line 5 : Module import itself
It looks like the module is importing itself.
Benutzeravatar
sparrow
User
Beiträge: 4197
Registriert: Freitag 17. April 2009, 10:28

Na, da sind doch schon alle Puzzlestücke.
Warum rufst du denn ein Modul "shelve" auf und importierst es dann in sich selbst?
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

hat sich erledigt, dass lag am Dateinamen - wieder was gelernt

Danke Dir
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

ich komme einfach nicht auf die Lösung. Mögt Ihr mir nochmal helfen?

ich habe beispielsweise folgende Liste:
[datetime.date(2022, 1, 27), datetime.date(2022, 1, 31), 5, datetime.date(2022, 2, 1), datetime.date(2022, 2, 3), 2.8571428571428568]

Die besteht aus aneinander gehegten Elementen. 1) datetime.date() 2) datetime.date() und 3) einem Faktor.
Die Anzahl der Elemente kann variieren.

Nun habe ich manuell mal das Wunschergebnis aufgebaut:
1) Die Liste soll in Blöcke (hier zwei) geteilt werden
[(datetime.date(2022, 1, 27), datetime.date(2022, 1, 31), 5), (datetime.date(2022, 2, 1), datetime.date(2022, 2, 3), 2.8571428571428568)]
2) Bestehend aus einem Paar von Datum und dahinter dem zugehörigem Faktor
3) Damit ich später darauf wie folgt zugreifen kann
2022-01-27

Das sollte doch eigentlich damit funktionieren, dass man
1) Die Anzahl der Blöcke ermittelt, die benötigt werden
anzahl_bloecke = len(NAME DER LISTE) / 3)
2) und dann mit einer for Schleife aufteilt
Aber genau das bekomme ich einfach nicht hin.
Mit der Methode .pop() lässt sich ein Datetime Objekt auch darüberhinaus nicht entnehmen.

Bestimmt denke ich wieder viel zu kompliziert.

Habt Ihr n Ansatz dafür, für mich?

Danke
Kai

PS Ja, ich sollte eigentlich versuchen die Liste direkt in dem gewünschten Format
zu erzeugen. Die ist aber so vorgegeben.
Benutzeravatar
__blackjack__
User
Beiträge: 13121
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@derkai74: Warum ist die denn von wem so vorgegeben?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

von dem, von dem die Daten herkommen :)
aber wir wollen ja ehrlich sein - von mir.

Ich erhalte diese Liste aus folgendem Code
(Bitte nicht gleich wieder über meine Namen schimpfen) :

Code: Alles auswählen

def berechne_datum_paare (startdatum, kosten_verteilung, budget, entlassung):
    
    liste = []
    tage = budget / kosten_verteilung
    print("Startdatum: ", startdatum)
    print("Entlassung: ", entlassung)
    print("Budget reicht für: ", tage)
    endedatum_budget = (addiere_tage(startdatum, tage))
    print("Ende Budget: ", endedatum_budget)
    echtes_ende = min(endedatum_budget, entlassung)
    print("Ende Abrechnung: ", echtes_ende)
    datum = startdatum
    print()
        
    while datum < echtes_ende:
        
        """ Wenn die Liste neu ist, ergänze das
            Aufnahmedatum, sonst überspringen """
        if len(liste) == 0:
            liste.append(startdatum)
        
        """ Da noch das Ende-Datum für die Abrechnung
            benötigt wird, wird hier das Ende
            Datum berechnet. Das ist entweder das Monatsende,
            wenn das Budget länger reicht, als das Monatsende, oder
            das Ende Datum des Budgets des Entlastungsbetrages """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31)
        
        liste.append(min(echtes_ende, berechne_monatsletzten(liste[-1])))
        
        """ Da es nun ein Datumspaar gibt, wird noch
            die Anzahl der Tage für die Abrechnung benötigt
            und in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4]
        
        zeitraum = (berechne_tagesanzahl(liste[-2], liste[-1]))
        if zeitraum < tage:
            liste.append(zeitraum)
            tage = tage - zeitraum
        else: liste.append(float(tage))
                                
              
        """ wenn das Ende noch nicht erreicht ist, wird
            ein neues 'Beginn - Datum ' in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4, datetime.date(2022, 2, 1)]
        if echtes_ende > liste[-2]:
            liste.append(addiere_tage(liste[-2],1))
            """ Damit die Schleife weiter läuft, da ja das
                Ende noch nicht erreicht ist, wird die Variable
                DATUM auf den letzten Eintrag in der Liste gesetzt.
                Der ist ja durch ein neues Beginn Datum ein Datum"""
            datum = liste[-1]
               
            """ Wenn kein neues Beginn Datum angelegt wurde,
                dann ist der letzte Eintrag ein Tag. Dann ist
                das letzte Datum das vorletzte Element der Liste.
                Das muss dann das Ende der Schleife sein """
        else:
            datum = liste[-2]
        
    return(liste)
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

ach so, der Vollständigkeit halber:
so rufe ich auf:

Code: Alles auswählen

startdatum = date(2022,1,27)
endedatum = date(2022,2,17)
x = berechne_datum_paare (startdatum, 140, 1100, endedatum)
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Ich habe den Code wie folgt umgeschrieben:

Code: Alles auswählen

from datetime import date
from Umwandlung import berechne_tagesanzahl
from Umwandlung import addiere_tage
from Umwandlung import berechne_monatsletzten

""" Diese Funktion berechnet eine Liste von
    relevanten Datumspaaren, und berechent die
    für die Abrechnung relevanten Tage als jeweils
    3. Element """

""" Übergeben wird ein Startdatum oder das Datum
    des Endes des Budgets """

def berechne_datum_paare (startdatum, kosten_verteilung, budget, entlassung):
    
    liste = []
    tage = budget / kosten_verteilung
    print("Startdatum: ", startdatum)
    print("Entlassung: ", entlassung)
    print("Budget reicht für: ", tage)
    endedatum_budget = (addiere_tage(startdatum, tage))
    print("Ende Budget: ", endedatum_budget)
    echtes_ende = min(endedatum_budget, entlassung)
    print("Ende Abrechnung: ", echtes_ende)
    datum = startdatum
    print()
       
    datum1 = ""
    datum2 = ""
       
    while datum < echtes_ende:
        
               
        """ Wenn die Liste neu ist, ergänze das
            Aufnahmedatum, sonst überspringen """
        if len(liste) == 0:
            datum1 = startdatum
        
        """ Da noch das Ende-Datum für die Abrechnung
            benötigt wird, wird hier das Ende
            Datum berechnet. Das ist entweder das Monatsende,
            wenn das Budget länger reicht, als das Monatsende, oder
            das Ende Datum des Budgets des Entlastungsbetrages """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31)
        
        datum2 = (min(echtes_ende, berechne_monatsletzten(datum1)))
        
        """ Da es nun ein Datumspaar gibt, wird noch
            die Anzahl der Tage für die Abrechnung benötigt
            und in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4]
        
        zeitraum = (berechne_tagesanzahl(datum1, datum2))
        if zeitraum < tage:
            faktor = zeitraum
            tage = tage - zeitraum
        else: faktor=float(tage)
        
        """ alle Daten sind gesammelt - schreibe Eintrag in Liste """
        
        liste.append((datum1, datum2, faktor))
                                
        """ wenn das Ende noch nicht erreicht ist, wird
            ein neues 'Beginn - Datum ' in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4, datetime.date(2022, 2, 1)]
        if echtes_ende > liste[-1][-2]:
            datum1 = addiere_tage(liste[-1][-2],1)
            
            """ Damit die Schleife weiter läuft, da ja das
                Ende noch nicht erreicht ist, wird die Variable
                DATUM auf den letzten Eintrag in der Liste +1 gesetzt.
                Der ist ja durch ein neues Beginn Datum ein Datum"""
            datum = datum1
                           
            """ Wenn kein neues Beginn Datum angelegt wurde,
                dann ist der letzte Eintrag ein Tag. Dann ist
                das letzte Datum das vorletzte Element der Liste.
                Das muss dann das Ende der Schleife sein """
        else:
            datum = liste[-1][-2]
        
    return(liste)
        


# ------------- Test Umwandlung der Liste

startdatum = date(2022,1,27)
endedatum = date(2022,2,17)
x = berechne_datum_paare (startdatum, 140, 1100, endedatum)
print(x)

derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Arbeite aber noch dran
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Ok, dann werde ich mich mal dieser Fassung zur Diskussion stellen.
Was ist gut, was ist schlecht und ist es zu kompliziert?
Ginge es einfacher?

"Feuer" frei.

Würde mich über Eure Meinungen freuen.

Vielen Dank vorab
Kai

Code: Alles auswählen

from datetime import date
from Umwandlung import berechne_tagesanzahl
from Umwandlung import addiere_tage
from Umwandlung import berechne_monatsletzten

""" Diese Funktion berechnet eine Liste von
    relevanten Datumspaaren, und berechent die
    für die Abrechnung relevanten Tage als jeweils
    3. Element """

""" Übergeben wird ein Startdatum oder das Datum
    des Endes des Budgets """

def berechne_datum_paare (startdatum, kosten_verteilung, budget, entlassung):
    
    liste = []
    tage = budget / kosten_verteilung
    print("Startdatum: ", startdatum)
    print("Entlassung: ", entlassung)
    print("Budget reicht für: ", tage)
    endedatum_budget = (addiere_tage(startdatum, tage))
    print("Ende Budget: ", endedatum_budget)
    echtes_ende = min(endedatum_budget, entlassung)
    print("Ende Abrechnung: ", echtes_ende)
    datum = startdatum
    print()
       
    datum1 = startdatum
    datum2 = ""
       
    while datum1 < echtes_ende:
        
               
        """ Wenn die Liste neu ist, ergänze das
            Aufnahmedatum, sonst überspringen """
        if len(liste) == 0:
            datum1 = startdatum
        
        """ Da noch das Ende-Datum für die Abrechnung
            benötigt wird, wird hier das Ende
            Datum berechnet. Das ist entweder das Monatsende,
            wenn das Budget länger reicht, als das Monatsende, oder
            das Ende Datum des Budgets des Entlastungsbetrages """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31)
        
        datum2 = (min(echtes_ende, berechne_monatsletzten(datum1)))
        
        """ Da es nun ein Datumspaar gibt, wird noch
            die Anzahl der Tage für die Abrechnung benötigt
            und in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4]
        
        zeitraum = (berechne_tagesanzahl(datum1, datum2))
        if zeitraum < tage:
            faktor = zeitraum
            tage = tage - zeitraum
        else: faktor=float(tage)
        
        """ alle Daten sind gesammelt - schreibe Eintrag in Liste """
        
        liste.append((datum1, datum2, faktor))
                                
        """ wenn das Ende noch nicht erreicht ist, wird
            ein neues 'Beginn - Datum ' in die Liste geschrieben """
            # Bsp: [datetime.date(2022, 1, 28), datetime.date(2022, 1, 31), 4, datetime.date(2022, 2, 1)]
        if echtes_ende > liste[-1][-2]:
            datum1 = addiere_tage(liste[-1][-2],1)
            
            """ Damit die Schleife weiter läuft, da ja das
                Ende noch nicht erreicht ist, wird die Variable
                DATUM auf den letzten Eintrag in der Liste +1 gesetzt.
                Der ist ja durch ein neues Beginn Datum ein Datum"""
                                       
            """ Wenn kein neues Beginn Datum angelegt wurde,
                dann ist das Ende erreicht. """
        else:
            break
        
    return(liste)
        




derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Ok, habe leider schon eine weitere Frage.
Ich habe ein "Hauptprogramm.
Es ist notwendig, dass durch den Nutzer 14 Einzelpositionen eingegeben werden müssen.
Daraus werden dann noch zusätzliche weitere Variablen berechnet.

Ich finde, dass das Hauptprogramm sehr unschick macht.
Nun habe ich die Erfassung dieser Daten in einer Funktion ausgegliedert.
Und rufe diese dann aus dem Hauptprogramm auf.

Aber die Variablen, Referenzen und somit Werte müssen
halt auch in dem Hauptprogramm zur Verfügung stehen.

Jetzt gäbe es die Möghlichkeit über eine retrun Anweisung dort wieder alles
zu entpacken. Dann hätte ich mir das auch sparen können.
Oder in der Funktion über globale Variablen zu Arbeiten.

Habt Ihr da n Tip für mich?

Danke
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

'global' -> nein, return -> ja.

Ich glaube das ganze ist an Hand deines Codes besser zu beurteilen.
Bis dahin, du kannst ja auch mit Listen oder ähnlichem arbeiten. Und wenn deine Variablen alle durchnummeriert sind, weil dir keine anderen Namen eingefallen sind, dann ist das nochmal ein Grund über Listen oder andere Datenstrukturen nachzudenken.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

Vielen Dank. Der Code ist insgesamt schon sehr
angewachsen. Und mit Listen arbeite ich schon umfänglich.

Trotzdem vielen Dank für die Rückmeldung.

Das Programm ist fertig.

Aber, ich finde es zu kompliziert aufgebaut.
Neben dem, dass ich natürlich noch viel Lernen muss.
Fehlt es mir aktuell einfach am Verständnis, wir man
so etwa überhaupt und strukturiert aufbaut.

Würde es helfen, ich skizziere mal dass Gesamtprojekt?
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Ich zeig dir mal ein Beispiel, wie ich das gemeint habe. Ob das zu deinem Code/Vorhaben passt weis ich natürlich nicht.

Code: Alles auswählen

#!/usr/bin/env python3

def make_something(answers):
    print([int(answer + 1 for answer in answers])

def take_user_input():
    answers = []
    for number in range(14):
        answers.append(input(f'Bitte {number}. Wert eingeben: '))
    return answers

def main():
    answers = take_user_input()
    make_something(answers)
    

if __name__ == '__main__':
    main()
Ich weis nicht ob andere User mit einer Skizze etwas anfangen können, ich denke ich eher nicht.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17757
Registriert: Sonntag 21. Oktober 2012, 17:20

@derkai74: zu Deiner Funktion `berechne_datum_paare`.
Literale Strings sind kein Ersatz für Kommentare. Ein Kommentar sollte beschreiben, warum man was macht, nicht wie.
Zeile 2-4: Module schreibt man komplett klein. Die Importe aus dem selben Modul können in eine Zeile geschrieben werden.
Zeile 15: Variablen initialisiert man erst, wenn man sie braucht, also `liste` direkt vor der while-Schleife.
Zeile 20: da sind Klammern zu viel
Zeile 24: `datum` wird nie benutzt.
Zeile 28: `datum2` hat hier den Typ String, sonst den Typ `datetime`. Sowas darf man nicht machen, eine Variable sollte immer nur Werte vom selben Typ haben.
Zeile 35: diese if-Abfrage ist doof. Die if-Abfrage ist nur im ersten Schleifendurchlauf wahr, also kann das vor der Schleife stehen, wo es aber schon steht.
Zeile 45, 52: zu viele Klammernpaare
Zeile 56: nach einem : fängt eine neue Zeile an. `tage` ist bereits ein float.
Zeile 65: warum rechnest Du den Index innerhalb des Tupels vom Ende her? -2 ist das selbe wie 1. Und das ist das selbe wie `datum2`.
Die if-Abfrage ist an sich unnötig, da wenn Du immer datum1 auf datum2+1 setzt, dann ist die while-Schleife automatisch zu Ende, weil die Bedingung am Anfang datum1 < echtes_ende ist.
Zeile 78: `return` ist keine Funktion, die Klammern daher verwirrend.

Die Variablennamen sind zum Teil schlecht, weil sie nicht wirklich aussagen, was sie enthalten.

Das mit dem Faktor verstehe ich nicht. Da echtes_ende `startdatum + tage` ist, kann `datum2` niemals mehr Tage nach dem startdatum liegen, als in der Variable `tage` steht, damit kann zeitraum niemals größer als `tage` sein, so dass die if-Abfrage zeitraum <= tage immer wahr ist.
Bleibt also

Code: Alles auswählen

from umwandlung import berechne_tagesanzahl, addiere_tage, berechne_monatsletzten

def berechne_datum_paare(startdatum, kosten_verteilung, budget, entlassung):
    """ Diese Funktion berechnet eine Liste von
        relevanten Datumspaaren, und berechent die
        für die Abrechnung relevanten Tage als jeweils
        3. Element """
    tage = budget / kosten_verteilung
    endedatum_budget = addiere_tage(startdatum, tage)
    echtes_ende = min(endedatum_budget, entlassung)

    print("Startdatum: ", startdatum)
    print("Entlassung: ", entlassung)
    print("Budget reicht für: ", tage)
    print("Ende Budget: ", endedatum_budget)
    print("Ende Abrechnung: ", echtes_ende)
    print()
       
    liste = []
    datum = startdatum
    while datum < echtes_ende:
        # Da noch das Ende-Datum für die Abrechnung
        # benötigt wird, wird hier das Ende
        # Datum berechnet. Das ist entweder das Monatsende,
        # wenn das Budget länger reicht, als das Monatsende, oder
        # das Ende Datum des Budgets des Entlastungsbetrages """
        enddatum = min(echtes_ende, berechne_monatsletzten(datum))
        zeitraum = berechne_tagesanzahl(datum, enddatum)
        liste.append((datum, enddatum, zeitraum))
        datum = addiere_tage(enddatum, 1)
        
    return liste
derkai74
User
Beiträge: 39
Registriert: Montag 27. Dezember 2021, 22:14

@sirius
Habe wirklich vielen Dank für Deine Rückmeldung und Mühe.

Ich habe / werde Teile davon übernehmen.
ABER, Dein Code führt zu einem falschen Ergebnis.

ıch analysiere noch warum.
Aber ich muss glaube ich dringend mal eine Skizze vom Endergebnis machen.
Antworten