Neuling sucht Rat
Eine Klasse `Logbook` oder `DriversLogbook` wäre wahrscheinlich näher am Problem. 

Code: Alles auswählen
import sys
import tkinter
class Traffic():
def startWert(self):
d = open("testtraffic.txt")
self.startWert = d.readline()
d.close()
try:
self.startWert = int(self.startWert)
except ValueError:
self.startWert = 0
except EnvironmentError:
self.startWert = 0
except FileNotFoundError:
self.startWert = 0
def standAnzeigen(self):
anzeige["text"] = "Der momentane Verbrauch liegt bei "+str(self.startWert)+" mb"
def neuerVerbrauch(self):
neuerVerbrauch = eingabe.get()
try:
neuerVerbrauch = int(neuerVerbrauch)
self.startWert += neuerVerbrauch
anzeige["text"] = "Der momentane Verbrauch liegt bei"+ str(self.startWert) +" mb."
except ValueError:
anzeige["text"] = "Falsche Eingabe, bitte eine Zahl eingeben."
def Resetten(self):
anzeige["text"] = "Aktuellen Stand zurückgesetzt"
startWert = 0
def verbrauchSchreiben(self):
d = open("testtraffic.txt","w")
d.write(str(self.startWert))
d.close()
Hm - wenn ich mich nicht irre ist def startWert eigentlich eine Eigenschaft und keine Methode?
Code: Alles auswählen
import sys
import tkinter
class Traffic():
def startWert(self):
d = open("testtraffic.txt")
self.startWert = d.readline()
d.close()
try:
self.startWert = int(self.startWert)
except ValueError:
self.startWert = 0
except EnvironmentError:
self.startWert = 0
except FileNotFoundError:
self.startWert = 0
def standAnzeigen(self):
anzeige["text"] = "Der momentane Verbrauch liegt bei "+str(self.startWert)+" mb."
def neuerVerbrauch(self):
neuerVerbrauch = eingabe.get()
try:
neuerVerbrauch = int(neuerVerbrauch)
self.startWert += neuerVerbrauch
anzeige["text"] = "Der momentane Verbrauch liegt bei "+ str(self.startWert) +" mb."
except ValueError:
anzeige["text"] = "Falsche Eingabe, bitte eine Zahl eingeben."
def Resetten(self):
anzeige["text"] = "Aktuellen Stand zurückgesetzt"
self.startWert = 0
def verbrauchSchreiben(self):
d = open("testtraffic.txt","w")
d.write(str(self.startWert))
d.close()
main.destroy()
traffic=Traffic()
traffic.startWert()
main = tkinter.Tk()
main.title("Traffic")
kopf=tkinter.Label(main, text="Herzlich willkommen",width=20,bg="yellow", relief="ridge",height = 2,font="Arial 20 bold")
kopf.pack()
anzeige=tkinter.Label(main, text="Anzeigefeld", font="bold", relief="ridge", bg="white")
anzeige.pack(fill="x")
aktuell=tkinter.Button(main, text="Wert anzeigen", command=traffic.standAnzeigen)
aktuell.pack(fill="x")
neuerVerbrauch=tkinter.Button(main, text="Neuer Verbrauch",command=traffic.neuerVerbrauch)
neuerVerbrauch.pack(fill="x")
eingabe=tkinter.Entry(main)
eingabe.pack(fill="x")
resetten=tkinter.Button(main, text="Trafficstand resetten",command=traffic.Resetten)
resetten.pack(fill="x")
ende=tkinter.Button(main,text="Ende",command=traffic.verbrauchSchreiben)
ende.pack(fill="x")
main.mainloop()
Im vergleich zu den Vorgänger muss nun nicht überall aus der Datei gelesen - bzw. in die Datei geschrieben werden.
Ebenso hab ich Abstand davon genommen 50 verschiedene Variablen zu benennen - was damals alterWert - neuerWert - aktuellerWert etc. war beschränkt
sich nun auf startWert und neuerVerbrauch, mir ist klar das startWert ein wohl etwas ungünstiger Name ist aber da fehlts mal wieder an Kreativität

der startWert wird jetzt einmalig vor(!) der main aufgerufen - das bedeutet man muss den Wert nicht überall abspeichern(wäre er in der main - würde er ohne ein speichern immer wieder den "altenWert" laden richtig?
Der neue Wert wird in die Datei geschrieben - wenn man das Programm beendet.
Das einzige "Problem" das ich momentan sehe ist - der X Button, aber nun gut - ihr werdet mich schon auf meine 100 Fehler aufmerksam machen

Btw - ich hab Traffic genommen - weil ich mit Logbook irgendwie nich so vorwärts kam:(
Das erste was mir sauer aufstößt; Du greifst aus Deiner Klasse auf Namen zu, welche weiter unten im Quelltext global gebunden werden. Das lässt sich nur sehr schwer nachvollziehen.
Traffic ist kein guter Name. Er beschreibt nicht das, was die Klasse darstellen soll. Traffic hat zu viele Aufgaben: Persistenz und (wirre) GUI-Anbindung.
Grüße ... bwbg
Traffic ist kein guter Name. Er beschreibt nicht das, was die Klasse darstellen soll. Traffic hat zu viele Aufgaben: Persistenz und (wirre) GUI-Anbindung.
Grüße ... bwbg
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Hallo Tengel,
Dein neuer Code wirkt schon viel aufgeräumter, und dazu sind ja Klassen unter anderem auch da.
Trotzdem haben sich noch ein paar Fehler und auch Unschönheiten eingeschlichen.
Schau mal nach, welche Exception von welcher Zeile in »startWert« geworfen werden kann. Du schreibst selbst, dass »startWert« vor jeder anderen Funktion aufgerufen werden muss, und genau das erledigt die »__init__«-Methode. Du überschreibst im übrigen die Methode »startWert« mit der Instanzvariable »startWert«. Das sollte nicht sein. Der Dateiname ist ein guter Kandidat dafür in der __init__-Methode als Argument übergeben zu werden.
Wenn Du das geschafft hast, solltest Du alles, was mit GUI zu tun hat in eine zweite Klasse schreiben, so dass Dein __main__-Teil nur noch aus dem erzeugen dieser Klasse und dem Aufruf von mainloop besteht.
Dein neuer Code wirkt schon viel aufgeräumter, und dazu sind ja Klassen unter anderem auch da.
Trotzdem haben sich noch ein paar Fehler und auch Unschönheiten eingeschlichen.
Schau mal nach, welche Exception von welcher Zeile in »startWert« geworfen werden kann. Du schreibst selbst, dass »startWert« vor jeder anderen Funktion aufgerufen werden muss, und genau das erledigt die »__init__«-Methode. Du überschreibst im übrigen die Methode »startWert« mit der Instanzvariable »startWert«. Das sollte nicht sein. Der Dateiname ist ein guter Kandidat dafür in der __init__-Methode als Argument übergeben zu werden.
Wenn Du das geschafft hast, solltest Du alles, was mit GUI zu tun hat in eine zweite Klasse schreiben, so dass Dein __main__-Teil nur noch aus dem erzeugen dieser Klasse und dem Aufruf von mainloop besteht.
wäre TrafficVerwaltung besser?Traffic ist kein guter Name
wie kann eine Klasse zu viele Aufgaben haben?
Code: Alles auswählen
Dein neuer Code wirkt schon viel aufgeräumte

?!?!Du überschreibst im übrigen die Methode »startWert« mit der Instanzvariable »startWert
mit dem Konstruktor in der Klasse?Der Dateiname ist ein guter Kandidat dafür in der __init__-Methode als Argument übergeben zu werden
Der wurde im Buch nur sehr "oberflächlich" genutzt
z. B.
Code: Alles auswählen
class Fahrzeug:
def __init__(self,bez,ge): #Konstruktormethode
self.bezeichnung = bez
self.geschwindigkeit = ge
def beschleunigen(self, wert):
self.geschwindigkeit += wert
self.ausgabe()
def ausgabe(self):
print(self.bezeichnung,self.geschwindigkeit,"km/h")
@Tengel: Ich würde die `__init__`-Methode nicht Konstruktor nennen. Die konstruiert kein neues Objekt, sondern initialisiert eines, welches es schon gibt und das ihr als erstes Argument übergeben wird. In anderen Sprachen könnte man das als semantische Haarspalterei bezeichnen, in Python gibt es allerdings auch eine `__new__()`-Methode, die *tatsächlich* ein Konstruktor ist.
Die `__init__()`-Methode ist wichtig. In der sollte ein Objekt vollständig initialisiert werden. Nachdem die abgelaufen ist, sollten alle Attribute existieren und sich das Objekt in einem konsistenten, benutzbaren Zustand befinden. Im Grunde der einzige Grund *keine* `__init__()` zu haben wäre eine Basisklasse deren `__init__()`-Methode genau das schon leistet, oder wenn man eine „mix in”-Klasse schreibt, die nicht eigenständig für sich existieren kann, sondern immer als zusätzliche Basisklasse von anderen Klassen verwendet werden muss.
Ad `startWert()`: Du hast auf dem Objekt eine Methode `startWert()` und in dieser Methode bindest Du einen Zahlenwert an das Attribut `startWert`. Damit hast Du die Methode überschrieben. Die kannst Du nur einmal aufrufen, danach hat das Objekt unter diesem Namen nicht mehr die Methode sondern den Zahlenwert gespeichert. Man kann nicht zwei verschiedene Sachen gleichzeitig an den selben Namen beziehungsweise das selbe Attribut binden.
Die `__init__()`-Methode ist wichtig. In der sollte ein Objekt vollständig initialisiert werden. Nachdem die abgelaufen ist, sollten alle Attribute existieren und sich das Objekt in einem konsistenten, benutzbaren Zustand befinden. Im Grunde der einzige Grund *keine* `__init__()` zu haben wäre eine Basisklasse deren `__init__()`-Methode genau das schon leistet, oder wenn man eine „mix in”-Klasse schreibt, die nicht eigenständig für sich existieren kann, sondern immer als zusätzliche Basisklasse von anderen Klassen verwendet werden muss.
Ad `startWert()`: Du hast auf dem Objekt eine Methode `startWert()` und in dieser Methode bindest Du einen Zahlenwert an das Attribut `startWert`. Damit hast Du die Methode überschrieben. Die kannst Du nur einmal aufrufen, danach hat das Objekt unter diesem Namen nicht mehr die Methode sondern den Zahlenwert gespeichert. Man kann nicht zwei verschiedene Sachen gleichzeitig an den selben Namen beziehungsweise das selbe Attribut binden.
Interessant
__init__ wirds als Konstruktor
__del__ als Desktruktor im Buch beschrieben
naja - das Buch wird wohl einen guten Türstopper/Briefbeschwerer abgeben - heute ist mein neues Buch gekommen - das werde ich nochmal von vorne durch arbeiten - da ich einiges ja schon "kenne" sollte es schneller gehen und evtl. kann ich so einge "Missstände" ausmerzen mal sehen
stimmt - da hab ich wieder nicht aufgepasst
ich werde die Methode mal umbenennen
__init__ wirds als Konstruktor
__del__ als Desktruktor im Buch beschrieben
naja - das Buch wird wohl einen guten Türstopper/Briefbeschwerer abgeben - heute ist mein neues Buch gekommen - das werde ich nochmal von vorne durch arbeiten - da ich einiges ja schon "kenne" sollte es schneller gehen und evtl. kann ich so einge "Missstände" ausmerzen mal sehen
stimmt - da hab ich wieder nicht aufgepasst

@Tengel: Üblicherweise benennt man Funktionen und Methoden nach Tätigkeiten. Wenn man in einer Methode zum Beispiel Daten aus einer Datei lädt, könnte man sie `load()` nennen. Oft wird so eine `load()`-Methode als Klassenmethode implementiert, also eine die nicht auf einem Exemplar aufgerufen wird und die Daten lädt und damit das Objekt verändert oder befüllt, sondern eine die auf der Klasse aufgerufen wird, die Daten lädt und dann ein neues Exemplar mit diesen Daten zurück gibt. Das musst Du jetzt noch nicht so machen, aber vielleicht im Hinterkopf behalten wenn Du zum Thema Klassenmethoden kommst.
`startWert` ist auch kein so passender Name denn erstens ist das nur am Anfang der Startwert, aber nicht mehr wenn man ihn verändert hat, und zweitens ist `Wert` sehr allgemein und beschreibt nicht was die Bedeutung des Wertes ist.
`startWert` ist auch kein so passender Name denn erstens ist das nur am Anfang der Startwert, aber nicht mehr wenn man ihn verändert hat, und zweitens ist `Wert` sehr allgemein und beschreibt nicht was die Bedeutung des Wertes ist.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Ja, du solltest dich fuer eine Sprache entscheiden 

Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Hm in meinem neuen Buch gibt es eine Fallstudie/Übungen mit TurtleWorld - ist das wirklich so "sinnvoll"?
Mein Problem ist dabei nicht das ich die Funktion nicht schreiben kann... die Funktionen an sich sind ja leicht - nur die Matheformeln ewig zu suchen .... ich weiß nicht wo das im Sinne von programmieren lernen helfen soll?
Mein Problem ist dabei nicht das ich die Funktion nicht schreiben kann... die Funktionen an sich sind ja leicht - nur die Matheformeln ewig zu suchen .... ich weiß nicht wo das im Sinne von programmieren lernen helfen soll?
Code: Alles auswählen
def hat_kein_e():
Wort_ohne_e = 0
woerter_gesamt = 0
d = open("Wortliste.txt")
for zeile in d:
woerter_gesamt = woerter_gesamt + 1
wort = zeile.strip()
if "e" not in wort and "E" not in wort:
print(wort)
Wort_ohne_e = Wort_ohnet_e + 1
else:
None
prozent = 100/woerter_gesamt*Wort_ohne_e
print(prozent)
d.close()
Wohl eher unnötig, genauso wie ein return am Ende jeder Funktion, einfach weil man es weglassen kann ohne die Funktion des Codes zu verändern. Ich würde sogar vermuten der kompilierte Bytecode sieht gleich aus.
Hier einige Denkanstöße:
Hier einige Denkanstöße:
Code: Alles auswählen
>>> with open('words.txt', 'r') as word_file:
... words = word_file.read().split()
...
>>> words
['affe', 'katze', 'hund']
>>> [word for word in words if "e" in word.lower()]
['affe', 'katze']
>>> len(words)
3