Globale Variable in Funktion erstellen

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
Spezmanu
User
Beiträge: 6
Registriert: Freitag 10. April 2009, 11:43
Kontaktdaten:

Hi Leutz,
ich will über eine Funktion einen Button erstellen und diesem über eine andere Funktion seine Position im Grid-Raster zuweisen.
das problem ist wenn ich ihn wie gewohnt erstelle (Button1=Tkinter.Button...)
dann greift die zweite funktion nicht auf ihn zu.
Die Funktionen befinden sich im übrigen in der gleichen Quellcode-Datei.

lg Manuel
Birne94
User
Beiträge: 90
Registriert: Freitag 28. November 2008, 15:18
Kontaktdaten:

globale Variablen sind eh nicht das beste o_O

Code: Alles auswählen

import Tkinter

button1 = None
def foo():
    global button1
    button1 = Tkinter.Button()
    # ...
so müsste es imo gehen, wenn ich dich richtig verstehe^^
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Sowas macht man normalerweise mit einer Klasse.
Spezmanu
User
Beiträge: 6
Registriert: Freitag 10. April 2009, 11:43
Kontaktdaten:

ich hatte mir eig gedacht, dass ich das außerhalb der funktion nicht deklarieren muss, da der Variablenname durch exec nicht immer gleich ist.
trotzdem danke
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Zeig doch mal deinen Code - global ist eigentlich fast nie nötig.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du solltest wirklich vergessen, dass es "global" und "exec" gibt und es mit vernünftigen Mitteln (Klassen, Parameter, Dictionaries für "dynamisch erstellte Variablen") lösen. Was du vor hast, wird aus Designsicht in einer Katastrophe enden. Die Wartbarkeit deines Codes wird unmöglich und unerwartete Seiteneffekte werden die Runde machen.
Das Leben ist wie ein Tennisball.
Spezmanu
User
Beiträge: 6
Registriert: Freitag 10. April 2009, 11:43
Kontaktdaten:

ich weiß, dass er unübersichtlich wird, deswegen kommentiere ich ja auch schon fleißig.
Aber mir persönlich fällt keine Alternativmöglichkeit ein.
Sinn des Programms ist es eine Veranstaltungsdatenbank zu verwalten, d.h. einfügen/ändern, drucken und löschen.
in der HTML-Version hatte ich die Auswahl mit ID und Eingabefeld gelöst, was ich nicht so toll fand.

Nun die Codes:

Code: Alles auswählen

def anlegen_pruef():
    # Überprüft/Korrigiert die Eingaben [gekürzt]
    # Danach werden die Button/Label der neuen Veranstaltung erstellt
    neu_ID=tele_sql.alle(['autoincrement'])['autoincrement']-1 #ID der eingegebenen Veranstaltung wird aus der DB gelesen
    neu_ver=tele_sql.suche(neu_ID,['ver_ID', 'ver_name','ver_ort','ver_datum','ver_time']) #Liest  in DB den Satz bei neu_ID aus; nur Listenelemente werden zurückgegeben
    global sqls
    sqls=tele_sql.alle(['ver_ID','ver_name','ver_ort','ver_datum','ver_time','autoincrement']) # alle Datensätze werden aus der DB gelesen; Liste enthält Spaltennamen
    # die folgenden exec's sind mein Problem
    exec 'global ver'+str(neu_ID)
    exec 'global ort'+str(neu_ID)
    exec 'global datum'+str(neu_ID)
    exec 'global pk'+str(neu_ID)
    # ubersicht ist der Frame
    exec 'ver'+str(neu_ID)+'=Tk.Radiobutton(ubersicht,indicatoron=0,text="'+neu_ver['ver_name'][0]+'",value='+str(neu_ID)+',variable=ver,command=ver_details).grid(column=1,sticky="we")'   # Erstellt Buttons mit dem Veranstaltungsnamen. Ein Klick zeigt die Maske zum Drucken, Löschen und Ändern an
    exec 'ort'+str(neu_ID)+'=Tk.Label(ubersicht,text="'+neu_ver['ver_ort'][0]+'").grid(column=2,sticky="we")'                                                                                          # Erstellt ein Label mit dem Veranstaltungsort
    exec 'datum'+str(neu_ID)+'=Tk.Label(ubersicht,text="'+neu_ver['ver_datum'][0]+' '+neu_ver['ver_time'][0]+'").grid(column=3,sticky="we")'                                                              # Erstellt ein Label mit Datum und Uhrzeit der Veranstaltung
    exec 'pk'+str(neu_ID)+'=Tk.Radiobutton(ubersicht,indicatoron=0,value='+str(neu_ID)+',variable=pk,command=pk_details).grid(column=4,sticky="we")'                                     # Erstellt einen Button ohne Aufschrift; ein Klick zeigt die Preisklassen der Veranstaltung an; siehe 'def pk_details' weiter oben.
    sort_ver() #folgender Code

Code: Alles auswählen

def sort_ver():
    # Sortiert die Tabelle in 'ubersicht' nach den Veranstaltungsnamen
    u1.config(font=("MS Sans Serif",8,"bold"))  # 'u1' ('Veranstaltung') wird hervorgehoben, um die aktuelle Sortierung zu zeigen.
    u2.config(font=("MS Sans Serif",8))
    u3.config(font=("MS Sans Serif",8))
    zusortieren=[]
    for i in range(len(sqls['ver_name'])):      # Der Datensatz mit den Veranstaltungsnamen wird durchlaufen
        zusortieren+=[[sqls['ver_name'][i].lower(),sqls['ver_ID'][i]]]  # Die Namen werden mit den zugehörigen IDs in 'zusortieren' kopiert; Groß-/Kleinschreibung wird irrelevant.
    zusortieren.sort()                          # Die Liste 'zusortieren' wird nach den Veranstaltungsnamen sortiert (Algorithmus von Python implementiert)
    for i in range(len(zusortieren)):           # Sortierte Liste 'zusortieren' wird durchlaufen
        # Die Tabelleninhalte werden nach der Reihenfolge in 'zusortieren' geordnet; Ausschlaggebend ist hierbei der Objektname:
        exec 'ver'+str(zusortieren[i][1])+'.grid(row='+str(i+3)+')'
        exec 'ort'+str(zusortieren[i][1])+'.grid(row='+str(i+3)+')'
        exec 'datum'+str(zusortieren[i][1])+'.grid(row='+str(i+3)+')'
        exec 'pk'+str(zusortieren[i][1])+'.grid(row='+str(i+3)+')'
Wer eine einfachere/verständlichere Form findet, kann sie gerne posten.
Ich hoffe ich hab an alle Variablen gedacht
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das kommt so sehr nah an den grausamsten Code ran, den ich jemals gesehen habe. Und das ist wirklich ernst gemeint!

Die globals kannst du dir sparen: alles was du in einer Funktion brauchst übergibst du als Parameter, alles was rausgehen soll als Rückgabewert. Wenn du feststellst, dass du unglaublich viele Parameter und Rückgabewerte haben solltest, dann ist das meist ein Hinweis auf ein schlechtes Design. Entweder macht die Funktion dann zu viel auf einmal und du solltest sie zerlegen oder du benötigst eine neue Struktur: Klassen, anderes Design, ...

Um die ganzen "exec"-Aufrufe zu vermeiden machst du daraus ein Dictionary mit deinen erzeugten Variablennamen als Schlüssel und den Widgets als Werte. Oder noch besser: die IDs als Schlüssel und alle dazugehörigen Widgets als ein Wert (über ein Tupel oder wieder ein Dictionary). Wenn du das korrigiert hast, dann kann man dir sicher weiterhelfen.

Noch ein paar weitere Tipps:

Du kannst direkt über Werte einer Liste iterieren, das "len" kannst du dir sparen. Wenn du dennoch den Index brauchst, da suche in der Dokumentation nach "enumerate".

Auch wenn du es nach den Verbesserungen nicht mehr brauchen wirst: Strings setzt man selten mit "+" zusammen, es gibt eine extra String-Formatting-Syntax. Steht auch in der Doku.

Benutze Konstanten!

Kommentare besser in eine Extrazeile und nicht hinten dran. Wie auch für den Code gilt: nicht mehr als 80 Zeichen pro Zeile.

Blick auf PEP8 würde nicht schaden.
Das Leben ist wie ein Tennisball.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

omg. Hast du mal das Python-Tutorial durchgearbeitet?
lunar

audax hat geschrieben:omg. Hast du mal das Python-Tutorial durchgearbeitet?
Nein, warum sollte er auch, dem Code nach zu urteilen hat er doch langjährige Erfahrung in PHP *scnr*


Edit: "wieso" durch "warum" ersetzt ;)
Zuletzt geändert von lunar am Sonntag 12. April 2009, 12:58, insgesamt 1-mal geändert.
nuss
User
Beiträge: 53
Registriert: Donnerstag 28. August 2008, 11:36

@lunar
lunar
BeitragVerfasst am: Sa Apr 11, 2009 15:37 Titel:
audax hat folgendes geschrieben:
omg. Hast du mal das Python-Tutorial durchgearbeitet?

Nein, wieso sollte er auch, dem Code nach zu urteilen hat er doch langjährige Erfahrung in PHP *scnr*
*loooooooooooool* *seehr herzhaft lach* *am kugel boden* ich mein *am boden kugeln*
nur das wieso hättest du durch warum ersetzen sollen ;)
lunar

nuss hat geschrieben:nur das wieso hättest du durch warum ersetzen sollen ;)
Mmmh, gibt es da irgendeinen bedeutenden semantischen Unterschied zwischen "wieso" und "warum", der mir entgangen ist?
nuss
User
Beiträge: 53
Registriert: Donnerstag 28. August 2008, 11:36

Ist Semantisch gesehen einwandfrei, klingt nur irgendwie
nicht so ganz richtig in meinen Ohren. Mag auch nur so'n kleiner Spleen sein,
oder ostwestfälischer Dialekt wie meine Freundin sagen würde. ;)

edit:
musste übrigens auch erste noch 2 mal drüber lesen, bis ich zum Schuluss gekommen bin, dasses korrect ist :D
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Komisch, nach meinem (quasi-)bayrischen Sprachgefühl hätte ich jetzt "wieso" für die preußischere [1] Variante gehalten.

[1] für bayrische Werte von "preußisch" natürlich...
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

nuss hat geschrieben:musste übrigens auch erste noch 2 mal drüber lesen, bis ich zum Schuluss gekommen bin, dasses korrect ist :D
Das erinnert mich an "Contactlinsen"-Schilder ^^
Neben "wieso" und "warum" hätten wir auch noch "weswegen" und "weshalb".
Das Leben ist wie ein Tennisball.
Spezmanu
User
Beiträge: 6
Registriert: Freitag 10. April 2009, 11:43
Kontaktdaten:

Mein letztes PY-Tutorial war vor vier Jahren und nannte sich Unterricht, bei dem unser Lehrer mit uns zusammen Python lernte.
Das mit PHP stimmt mehr oder weniger, das hatte ich auf meine Profektpartnerin abgewälzt, während ich mich mit der Druckersprache abgequält hatte.

------------
Genitiv ins mehr, denn es ist Dativ.
Antworten