name is assigned to before global declaration

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
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Hallo Python-Gemeinde


Beim Starten meines Programm erhalte ich immer den gleichen Fehler:

Warning (from warnings module):
File "E:\*\*\*\*.pyw", line 112
def vzzp(self):
SyntaxWarning: name 'vzzpan' is assigned to before global declaration

Sobald ich aber das global vor "vzzpan" entferne, erhalte ich zwar die Fehlermeldung nicht mehr, aber mein Programm läuft nicht mehr.

Folgendes habe ich noch herausgefunden:

Ich mache die Variabel vzzpan zweimal global verfügbar,
aber sie wird in einer nächsten definierten Funktion geändert, deshalb muss ich sie ja wieder global machen.

Vielen Dank im Voraus
Zuletzt geändert von python-user am Montag 4. September 2006, 14:19, insgesamt 1-mal geändert.
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Etwas Beispiel-Code wäre sicher hilfreich ;)

Und wieso Variable vzzp, laut der Fehlermeldung heißt deine Funktion so? Solche Überschneidung sollte man vermeiden, genauso wie globale Variablen. Wenn sie in einer Funktion benötigt wird dann übergieb sie doch. Oder spricht da was gegen?
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Siehe PN;-)

Ich erstelle am Anfang des Programmes zwei Variabeln:

vzzpan = 0
vban = 0

Aus dem Programm heraus können dann zwei Funktionen aufgerufen werden. Die einte Funktion ändert den Wert auf:

vzzpan = 1
global vzzpan

Die andere Funktion ändert den Wert auf:

vb = 1
global vb

(Man führt aber immer nur eine Funktion aus!)

Mit einer dritten Funktion werden die Werte von vzzpan und vban überprüft und falls 1, geschieht etwas.

Startet man das Programm, dann motzt er, dass ich zweimal global benutzt habe, aber ohne geht es nicht!

mfg
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Ok, Grundlagen 1:

Wenn du die Funktion so definierst

Code: Alles auswählen

def meine_funktion(argument1)
    argument1 = argument1 + 1
    return argument1
dann kannst du sie mit

Code: Alles auswählen

variable1 = 0
variable1 = meine_funktion(variable1)
aufrufen.

Die Variable wird an die Funktion übergeben, in der Funktion heißt sie dann argument 1 (kannst sie auch wieder variable1 nennen, wenn du willst), dort wird etwas damit gemacht, und dann wird das argument1 zurückgegeben, und wieder der variable1 zugewiesen.

Da es bei dir " def vzzp(self): " heißt vermute ich, du befindest dich innerhalb einer Klasse?

Dann kannst du die Variable auch mit self.variable1 definieren, dann können alle Methoden der Klasse darauf zugreifen.
Zuletzt geändert von Nirven am Montag 4. September 2006, 14:31, insgesamt 1-mal geändert.
BlackJack

python-user hat geschrieben:Warning (from warnings module):
File "E:\*\*\*\*.pyw", line 112
def vzzp(self):
SyntaxWarning: name 'vzzpan' is assigned to before global declaration

Sobald ich aber das global vor "vzzpan" entferne, erhalte ich zwar die Fehlermeldung nicht mehr, aber mein Programm läuft nicht mehr.
Die Fehlermeldung sagt, dass der Name `vzzpan` an etwas gebunden wird bevor er als global deklariert wird. Du musst ihn erst als global deklarieren und dann erst eine Zuweisung machen.

Oder wie Nirven schon sagte: Übergib `vzzpan` als Argument an die Funktion(en) und binde den Rückgabewert wieder an diesen Namen. Das ist sauberer als ``global``.
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

BlackJack hat geschrieben:
python-user hat geschrieben:Warning (from warnings module):
File "E:\*\*\*\*.pyw", line 112
def vzzp(self):
SyntaxWarning: name 'vzzpan' is assigned to before global declaration

Sobald ich aber das global vor "vzzpan" entferne, erhalte ich zwar die Fehlermeldung nicht mehr, aber mein Programm läuft nicht mehr.
Die Fehlermeldung sagt, dass der Name `vzzpan` an etwas gebunden wird bevor er als global deklariert wird. Du musst ihn erst als global deklarieren und dann erst eine Zuweisung machen.

Oder wie Nirven schon sagte: Übergib `vzzpan` als Argument an die Funktion(en) und binde den Rückgabewert wieder an diesen Namen. Das ist sauberer als ``global``.
Habe jetzt jetzt zuerst global deklariert und dann die Zuweisung gemacht - es geht!

Frage: Wie mache ich das mit dem Übergeben und dem Rückgabewert?

Man lernt nie aus :P

Danke für deine Hilfe!

Edit (Leonidas): BBCode aktiviert.
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Wie eine Übergabe und Rückgabe grundsätzlich funktioniert habe ich weiter oben schon beschriben.

Kannst du sonst vielleicht einen teil des Programmcodes posten, daran etwas zu zeigen ist einfacher als an einem abstrakten Beispiel.
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Nirven hat geschrieben:Wie eine Übergabe und Rückgabe grundsätzlich funktioniert habe ich weiter oben schon beschriben.

Kannst du sonst vielleicht einen teil des Programmcodes posten, daran etwas zu zeigen ist einfacher als an einem abstrakten Beispiel.
Besten Dank für deine Hilfe!

Habe den Post oben noch gar nicht gesehen.

Werde es nun so einrichten.

Wieder was gelernt, danke! :P

mfg

Edit (Leonidas): BBCode aktiviert.
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Hallo zusammen!

Da bin ich wieder:-)

Folgendes Problem habe ich:

Code: Alles auswählen

  
def vzzp(self): 
      # Der Anfangs- und Endpunkt wird global verfügbar gemacht
      global punkt1x
      global punkt1y
      global punkt1z
      global punkt2x
      global punkt2y
      global punkt2z

      global va

      # Funktion "Vektor zwischen zwei Punkten" wird nun generiert
      
      self.fenster.text3.config(text = "Vektor zwischen zwei Punkten:")

      self.fenster.punkt1 = Label(master = self.fenster)
      self.fenster.punkt1.pack()
      self.fenster.text4 = Label(master = self.fenster.punkt1,
                               text = "Bitte geben Sie die Koordinaten des Anfangspunktes ein: ",
                               font = (schrifttyp, 12))
      self.fenster.text4.pack(side = LEFT)
      self.fenster.punkt1x = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1x.pack(side = RIGHT)
      self.fenster.punkt1y = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1y.pack(side = RIGHT)
      self.fenster.punkt1z = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1z.pack(side = RIGHT)                                        

      self.fenster.punkt2 = Label(master = self.fenster)
      self.fenster.punkt2.pack()
      self.fenster.text5 = Label(master = self.fenster.punkt2,
                               text = "Bitte geben Sie die Koordinaten des Endpunktes ein:        ",
                               font = (schrifttyp, 12))
      self.fenster.text5.pack(side = LEFT)
      self.fenster.punkt2x = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2x.pack(side = RIGHT)
      self.fenster.punkt2y = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2y.pack(sid = RIGHT)
      self.fenster.punkt2z = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2z.pack(side = RIGHT)

      self.fenster.ausrechnen1 = Label(master = self.fenster)
      self.fenster.ausrechnen1.pack()      
      self.fenster.button1 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor ausrechnen",
                                    font = (schrifttyp, 12),
                                    command = va)
      self.fenster.button1.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
      self.fenster.button2 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor ausrechnen & zeichnen",
                                    font = (schrifttyp, 12),
                                    command = vauz)
      self.fenster.button2.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
      self.fenster.button3 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor zeichnen",
                                    font = (schrifttyp, 12),
                                    command = vz)
      self.fenster.button3.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
Dies ist ein Teil der grafischen Oberfläche, die einen Anfangspunkt und Endpunkt eines Vektors abfragt.

Nun habe ich ganz unten im Programm das "Kommando" va definiert:

Code: Alles auswählen

def va(): # Definition der Funktion "Vektor ausrechnen"
    print "bla"
    a = int(punkt1x.get())
    b = int(punkt1y.get())
    c = int(punkt1z.get())
    d = int(punkt2x.get())
    e = int(punkt2y.get())
    f = int(punkt2z.get())
Doch wenn ich dann das Programm starte und die Funktion va aufgerufen wird, erhalte ich folgenden Fehler:
bla
Exception in Tkinter callback
Traceback (most recent call last):
File "D:\Programme\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
return self.func(*args)
File "E:\Dateien\Schule\Maturaarbeit\Vektor-Programm 0.1.pyw", line 311, in va
a = int(punkt1x.get())
NameError: global name 'punkt1x' is not defined
Wo liegt das Problem? punkt1x ist ja definiert mit einem Entry und ist auch global verfügbar gemacht.

Sitze schon den ganzen Nachmittag dran und habe alles mögliche ausprobiert :-( Wisst ihr vielleicht etwas?

mfg
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

punkt1x ist ein attribut von self.fenster, keine globaler name.
Monk
User
Beiträge: 16
Registriert: Montag 28. August 2006, 11:27

Hallo

global heisst: Verwende eine vorhandene globale Variable statt eine neue lokale zu erstellen. Durch die Deklaration als global erstellst Du keine neue globale Variable!

Versuch also im Code zu schreiben:

Code: Alles auswählen

punkt1x=0
punkt1y=0
punkt1z=0
punkt2x=0
punkt2y=0
punkt2z=0
Abgesehen davon: Bei Vektoren gewinnst Du unheimlich, wenn Du für jeden Vektor ein Tupel benutzt: Also statt obigem würde ich eher schreiben:

Code: Alles auswählen

punkt1=(0,0,0)
punkt2=(0,0,0)
Dann kannst Du Deinen Start-und Endpunkt auch als Parameter übergeben und brauchst gar keine häßlichen globals mehr *brrrr*
Abgesehen davon ähnelt diese Notation der mathematischen Schreibweise so sehr, dass Dein Code auch lesbarer ist.

Gruß, der Monk
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Monk hat geschrieben:Hallo

global heisst: Verwende eine vorhandene globale Variable statt eine neue lokale zu erstellen. Durch die Deklaration als global erstellst Du keine neue globale Variable!

Versuch also im Code zu schreiben:

Code: Alles auswählen

punkt1x=0
punkt1y=0
punkt1z=0
punkt2x=0
punkt2y=0
punkt2z=0
Abgesehen davon: Bei Vektoren gewinnst Du unheimlich, wenn Du für jeden Vektor ein Tupel benutzt: Also statt obigem würde ich eher schreiben:

Code: Alles auswählen

punkt1=(0,0,0)
punkt2=(0,0,0)
Dann kannst Du Deinen Start-und Endpunkt auch als Parameter übergeben und brauchst gar keine häßlichen globals mehr *brrrr*
Abgesehen davon ähnelt diese Notation der mathematischen Schreibweise so sehr, dass Dein Code auch lesbarer ist.

Gruß, der Monk
Herzlichen Dank für deine Verbesserungsvorschläge!

Ich habe jetzt ganz am Anfang zwei Tupels erstellt:

Code: Alles auswählen

punkt1=(0,0,0)
punkt2=(0,0,0)
Also so, wie du gesagt hast.

Code: Alles auswählen

self.fenster.punkt1x = Entry(master = self.fenster.punkt1)
self.fenster.punkt1x.pack(side = RIGHT)
Doch wie ordne ich jetzt die 6 Entrys den jeweiligen Tupelstellen zu?

mfg
Monk
User
Beiträge: 16
Registriert: Montag 28. August 2006, 11:27

Mit globals:

Code: Alles auswählen

global punkt1, punkt2
punkt1=(self.fenster.punkt1x.get(), self.fenster.punkt1y.get(), self.fenster.punkt1z.get())
# ... usw.
Gruß, der Monk
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

Am Anfang der Datei:

Code: Alles auswählen

global punkta
global punkte
punkta=(0,0,0)
punkte=(0,0,0)
Dann wird eine Funktion definiert:

Code: Alles auswählen

  def vzzp(self): # Definition der Funktion "Vektor zwischen zwei Punkten"
      global va

      # Funktion "Vektor zwischen zwei Punkten" wird nun generiert
      
      self.fenster.text3.config(text = "Vektor zwischen zwei Punkten:")

      self.fenster.punkt1 = Label(master = self.fenster)
      self.fenster.punkt1.pack()
      self.fenster.text4 = Label(master = self.fenster.punkt1,
                               text = "Bitte geben Sie die Koordinaten des Anfangspunktes ein: ",
                               font = (schrifttyp, 12))
      self.fenster.text4.pack(side = LEFT)
      self.fenster.punkt1x = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1x.pack(side = RIGHT)
      self.fenster.punkt1y = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1y.pack(side = RIGHT)
      self.fenster.punkt1z = Entry(master = self.fenster.punkt1)
      self.fenster.punkt1z.pack(side = RIGHT)                                        

      self.fenster.punkt2 = Label(master = self.fenster)
      self.fenster.punkt2.pack()
      self.fenster.text5 = Label(master = self.fenster.punkt2,
                               text = "Bitte geben Sie die Koordinaten des Endpunktes ein:        ",
                               font = (schrifttyp, 12))
      self.fenster.text5.pack(side = LEFT)
      self.fenster.punkt2x = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2x.pack(side = RIGHT)
      self.fenster.punkt2y = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2y.pack(sid = RIGHT)
      self.fenster.punkt2z = Entry(master = self.fenster.punkt2)
      self.fenster.punkt2z.pack(side = RIGHT)

      self.fenster.ausrechnen1 = Label(master = self.fenster)
      self.fenster.ausrechnen1.pack()      
      self.fenster.button1 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor ausrechnen",
                                    font = (schrifttyp, 12),
                                    command = va)
      self.fenster.button1.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
      self.fenster.button2 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor ausrechnen & zeichnen",
                                    font = (schrifttyp, 12),
                                    command = vauz)
      self.fenster.button2.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
      self.fenster.button3 = Button(master = self.fenster.ausrechnen1,
                                    text = "Vektor zeichnen",
                                    font = (schrifttyp, 12),
                                    command = vz)
      self.fenster.button3.pack(side = LEFT,
                                padx = 10,
                                pady = 10)
"Kommando" va:

Code: Alles auswählen

def va(): # Definition der Funktion "Vektor ausrechnen"
    print "bla"
    punkta = (punkt1x.get(), punkt1y.get(), punkt1z.get())
    punkte = (punkt2x.get(), punkt2y.get(), punkt2z.get()) 
Starte ich nun das Programm, erhalte ich folgende Fehlermeldung:
bla
Exception in Tkinter callback
Traceback (most recent call last):
File "D:\Programme\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
return self.func(*args)
File "E:\Dateien\Schule\Maturaarbeit\Vektor-Programm 0.1.pyw", line 308, in va
punkta = (punkt1x.get(), punkt1y.get(), punkt1z.get())
AttributeError: 'int' object has no attribute 'get'
Muss ich doch noch alle punkt1x, punkt1y usw. global machen?
BlackJack

Nein Du solltest die wirklich besser als Argumente übergeben. Und Dir vielleicht an einem etwas kleinerem Beispiel klar machen wie das mit den Namensräumen funktioniert.

``global`` auf Modulebene macht überhaupt keinen Sinn, weil es keine Wirkung hat. Mit ``global`` kann man nur innerhalb von Funktionen und Methoden etwas ausrichten. Ohne diese Deklaration ist jeder Name der innerhalb der Funktion an ein Objekt gebunden wird ein lokaler Name der nicht ausserhalb der Funktion sichtbar ist.

Auch das ``global va`` macht keinen Sinn, da du diesen Namen von der Modulebene innerhalb der Methode nur benutzt und nicht neu bindest.

Du könntest innerhalb der `vzzp()` Methode eine lokale Funktion definieren, welche die Werte aus der GUI ausliest, die Berechnungsfunktion durchführt und das Ergebnis darstellt. Oder anstelle einer lokalen Funktion eine weitere Methode die das tut. Ungefähr so:

Code: Alles auswählen

    def va_command(self):
        punkt_a = (self.fenster.punkt1x.get(),
                   self.fenster.punkt1y.get(),
                   self.fenster.punkt1z.get())
        punkt_b = (self.fenster.punkt2x.get(),
                   self.fenster.punkt2y.get(),
                   self.fenster.punkt2z.get())
        ergebnis = va(punkt_a, punkt_b)
        # Ergebnis darstellen.

def va(punkt_a, punkt_b):
    print 'bla'
    # Irgend etwas mit den Punkten machen.
    return ergebnis
Und Du solltest vielleicht etwas an den Namen ändern -- `vzzp` und `va` sind recht nichtssagend.
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

@BlackJack:

Bin am Ende und komm einfach nicht weiter, hab dir jetzt den ganzen Quelltext per PM geschickt;-)
BlackJack

Hm, da bekomme ich vom Forum leider einen `Internal Server Error`. :-(
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

BlackJack hat geschrieben:Hm, da bekomme ich vom Forum leider einen `Internal Server Error`. :-(
Ja, erhielt diesen auch, als ich es ein zweites Mal schicken wollte.

Naja, habs dir jetzt per Mail geschickt.
python-user
User
Beiträge: 21
Registriert: Montag 4. September 2006, 13:44

python-user hat geschrieben:
BlackJack hat geschrieben:Hm, da bekomme ich vom Forum leider einen `Internal Server Error`. :-(
Ja, erhielt diesen auch, als ich es ein zweites Mal schicken wollte.

Naja, habs dir jetzt per Mail geschickt.
Hast du es bekommen?
Antworten