Zugriff auf globale Variable

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.
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

Hallo Liebes Board,

zunächst einmal nutze ich meinen ersten Thread um mein Projekt kurz vorzustellen. Ich bin zurzeit Schüler in der (bald) 12. Klasse eines Gymnasiums und schreibe meine Facharbeit über ein von mir selbst programmiertes Pythonspiel.
Und gerade dieses bereitet mir öfter mal sehr viel Kopfzerbrechen, weshalb ich wohl noch öfter hier mit einigen Fragen im Gepäck auftauchen werde.
Ich will klarstellen, dass ich von euch nicht mein Spiel programmiert haben will, ich stoße bloß leider mit Python zu oft an meine Grenzen, weshalb ich immer mal wieder kleine Unterstützung brauche, ich bin natürlich trotzdem für jegliche Tipps offen!


Nun zu meinem ersten, wahrscheinlich recht simplen Problem:

Ich erstelle zum Starten des Spiels ein Globales objekt einer Klasse, welches später mal alle anderen Klassen verwalten soll. Nun möchte ich auf dieses Objekt in einer Methode einer anderen Klasse zugreifen, was so aber nicht zu funktionieren scheint.
Die Fehlermeldung lautet:
Traceback (most recent call last):
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel.py", line 72, in <module>
s = Spiel()
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel.py", line 8, in __init__
self.g = Grafik()
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel.py", line 24, in __init__
self.z.fahren()
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel.py", line 59, in fahren
self.c = s.self.g.getCanvas()
NameError: global name 's' is not defined
Hier der dazugehörige Code:

Code: Alles auswählen

from Tkinter import *
from threading import *
from time import *
import thread

class Spiel:
    def __init__(self):
        self.g = Grafik()
    
class Grafik:
    def __init__(self):
        fenster = Tk()
        self.h=Hintergrund()
        self.c = Canvas(width=self.h.getHintergrundWidth(),height=self.h.getHintergrundHeight())
        self.c.pack()
        self.hintergrund = self.h.getHintergrund()
        self.c.create_image(0,0,image=self.hintergrund,anchor=NW)
        print "Canvas created"

        self.z=Zug()
        self.zug = self.z.zugSetzen(self.c)
        self.c.create_image(0,138,image=self.zug,anchor=NW,tags='zugtag')
        #thread.start_new_thread(self.fahren(),(1000, ))
        self.z.fahren()
        self.gleise = [0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23]
        for i in range(23):
            self.gleise[i] = PhotoImage(file = "C:\Users\Manuel\Schule\Informatik_Seminar\gleis.gif")
            self.c.create_image(i*20,169,image=self.gleise[i],anchor=NW)
            
        fenster.mainloop()
        
    def getCanvas(self):
        return self.c
    

class Hintergrund:
    def __init__(self):
        self.hintergrund1 = PhotoImage(file = "C:\Users\Manuel\Schule\Informatik_Seminar\hintergrund2.gif")
        
    def getHintergrund(self):           
        return self.hintergrund1

    def getHintergrundWidth(self):
        self.hwidth = self.hintergrund1.width()

        return self.hwidth

    def getHintergrundHeight(self):
        self.hheight = self.hintergrund1.height()

        return self.hheight
        

class Zug(Thread):
    def __init__(self):
        Thread.__init__(self)

    def fahren(self):
        self.c = s.self.g.getCanvas()
        for x in range(100):
            self.c.move('zugtag',5,0)
            time.sleep(100)
            print "Bewegung um 5"
            
            
    def zugSetzen(self,canvas):
        zug1 = PhotoImage(file = "C:\Users\Manuel\Schule\Informatik_Seminar\Zug.gif")

        return zug1

print "hallo1"
s = Spiel()
print "hallo2"
" def fahren(self):
self.c = s.self.g.getCanvas()" Hier möchte ich das Objekt von ganz unten Benutzen.

Vielen Dank schonmal für zügige Antworten,

Bonsai
Zuletzt geändert von Anonymous am Montag 20. August 2012, 11:07, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
deets

Warum uebergibst du Grafik nicht das self von Spiel, und wiederum Zug das spiel innerhalb des __init__ von Grafik? Dann kannst du in Zug self.spiel sagen, statt mit globalen Variablen zu arbeiten.

Und dann noch ein Hinweis: du wirst mit Threads nicht gluecklich werden. Threads + GUI funktioniert nicht wirklich. Benutze stattdessen die Funktion after in Tk um periodisch GUI-updates durchzufuehren.
BlackJack

@Bonsai: So etwas möchtest Du gar nicht erst versuchen. Wenn Du auf ein Objekt zugreifen möchtest, dann übergibt es als Argument. Entweder direkt an eine Methode oder an die `__init__()` der Klasse damit es dort für die spätere Verwendung in der Methode an das Objekt gebunden werden kann.

Dann solltest Du die Sternchen-Importe sein lassen und entweder über das Modul auf die Objekte darin zugreifen oder explizit nur die Namen importieren, die Du auch tatsächlich verwendest. Momentan importierst Du Unmengen an Namen in das Modul und man kann schlecht nachvollziehen welcher Name von wo kommt.

Das `thread`-Modul ist „deprecated” und sollte folglich nicht mehr verwendet werden. Und Threads funktionieren nicht so einfach mit GUI-Toolkits weil man die GUI nur aus dem Thread heraus manipulieren darf, in dem auch die Hauptschleife läuft.

Die ganzen einbuchstabigen Attributnamen sollten durch sinnvolle Namen ersetzt werden die möglichst ohne raten zu müssen dem Leser erlauben zu verstehen was der Wert hinter dem Namen bedeutet. Die Namensgebung hält sich auch nicht an PEP 8 -- Style Guide for Python Code.

Triviale Getter- und Setter-Methoden sind in Python unüblich.

Alle Attribute eines Objektes sollten nach abarbeitung der `__init__()` existieren. Man führt keine neuen Attribute in beliebigen Methoden ein wenn man nachvollziebare Programme schreiben möchte.

GUI und Geschäftslogik sollte man trennen. Ein Modell des Spiels für das man ohne GUI automatisierte Tests schreiben kann und bei dem man verschiedene GUIs „drauf setzen” kann, führt zu einem saubereren Entwurf.

`Grafik.gleise` wird „unpythonisch” erstellt. Statt eine Liste mit sinnlosen Werten zu erstellen und die dann der Reihe nach durch die eigentlichen Werte über Indexzuweisung zu ersetzen, würde man die Liste mit der `append()`-Methode oder über eine „list comprehension” erstellen.

Wenn immer das selbe Gleisbild verwendet wird, sollte man vielleicht auch nur *ein* `PhotoImage`-Objekt davon erzeugen.

In Python 2.x sollten Klassen von `object` erben, damit so schicke Sachen wie `property()` funktionieren.
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

*puh*

danke für die antworten. Mir war bewusst dass ich bisher schlampig angefangen habe, aber dass es so schlimm ist hätte ich nicht gedacht!
Ich hab nicht alles von der Kritik verstanden, aber ich werde mich heute Abend mal hinsetzen und versuchen das Programm so gut wie möglich euren Vorschlägen anzupassen.

Der Tipp das Threads mit tkinter nicht funktionieren erscheint mir sehr hilfreich, da ich von vielen Kollegen schon erfahren habe, dass ihr Programm nicht wirklich flüssig zu spielen ist, obwohl sie noch lange kein fertiges Spiel haben.

MfG Bonsai
deets

Noch ein weiterer Hinweis: deine Pfade enthalten backslashes, die nicht escaped sind (also einfach und nicht doppelt da stehen). Das wird dir frueher oder spaeter auf die Fuesse fallen, wenn du zB \n in dem Pfad stehen hast: "C:\foo\bar\neue dateien"


Entweder

- forward-slashes benutzen (klappt auch unter Windows)
- \\ statt \ benutzen
- raw-strings benutzen: r"foo\na\du" (beachte das kleine r vor dem ")
- os.path.join benutzen, und relative Pfade zu deinem __file__. Dann klappt das ganze auch unter Linux bzw. hard-kodierte Pfade.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Bonsai hat geschrieben:Mir war bewusst dass ich bisher schlampig angefangen habe, aber dass es so schlimm ist hätte ich nicht gedacht!
Du stößt ja hier auch auf den Versuch der Perfektion. :-)

Arbeite einfach eins nach dem anderen ab. Das wird schon.
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

So, ich hab nun iweder etwas rumprobiert und einige Sachen verbessert. Ich hab mir gedacht bevor ich wieder ein neues Thema aufmache, bleibe ich lieber bei dem Alten, ich hoffe das ist für die Moderatoren in Ordnung so!?

Das Problem mit der globalen Variable habe ich so gelöst wie ihr es vorgeschlagen habt, ich habe die Objekte den Klassen übergeben, nun bin ich auch schon so weit gekommen, dass ich den Zug eigentlich fahren lassen könnte, leide funktioniert die funtion sleep() aus dem importierten time Modul nicht und ich weiß nicht warum, weil ich die Fehlermeldung nicht verstehe.
Traceback (most recent call last):
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel_2.py", line 100, in <module>
s = Spiel() #Starten des Spiels
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel_2.py", line 9, in __init__
self.g = Grafik(self)
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel_2.py", line 38, in __init__
self.z.fahren()
File "C:\Users\Manuel\Schule\Informatik_Seminar\Spiel_2.py", line 84, in fahren
time.sleep(100)
AttributeError: 'builtin_function_or_method' object has no attribute 'sleep'
>>>
hier ist mein neuer, kommentierter Code :D

Code: Alles auswählen

# -*- coding: cp1252 -*-

from Tkinter import *                   #verwendete GUI: Tkinter
from time import *                      #Modul zur Steuerung von zeitlichen Abläufen

#Klasse zur Steuerung des Spiels
class Spiel:
    def __init__(self):
        self.g = Grafik(self)
        
#Klasse zur Abbildung von Objekten auf dem Canvas
class Grafik:
    def __init__(self, spiel):
        self.spiel = spiel

        #Tkinter-Interface
        fenster = Tk()
        
        #Erzeugen eines Hintergrundobjekts
        self.h=Hintergrund()
        
        #Canvas
        self.c = Canvas(width=self.h.getHintergrundWidth(),height=self.h.getHintergrundHeight())
        self.c.pack()
        
        #Hintergrund
        self.hintergrund = self.h.getHintergrund()
        self.c.create_image(0,0,image=self.hintergrund,anchor=NW)
        print "Canvas created"

        #Zug
        self.z=Zug(self)
        self.zug_X = 0
        self.zug_Y = 0
        self.zug = self.z.zugSetzen(self.c)
        self.c.create_image(self.zug_X,self.zug_Y,image=self.zug,anchor=NW,tags='zugtag')
        self.z.setZugKoordinaten(self.zug_X, self.zug_Y)
        self.z.fahren()

        ###########################################
        #wird noch ausgelagert in eigene Klasse
        self.gleise = [0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23]
        for i in range(23):
            self.gleise[i] = PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/gleis.gif")
            self.c.create_image(i*20,169,image=self.gleise[i],anchor=NW)
        ###########################################
        
        fenster.mainloop()

    def getCanvas(self):
        return self.c

#Klasse für die Hintergrundobjekte        
class Hintergrund:
    def __init__(self):
        self.hintergrund1 = PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/hintergrund2.gif")
        
    def getHintergrund(self):           
        return self.hintergrund1

    def getHintergrundWidth(self):
        self.hwidth = self.hintergrund1.width()

        return self.hwidth

    def getHintergrundHeight(self):
        self.hheight = self.hintergrund1.height()

        return self.hheight
        
#Klasse für den fahrenden Zug
class Zug:
    def __init__(self, grafik):
        self.grafik = grafik

        self.x = 0
        self.y = 0

    def fahren(self):
        self.c = self.grafik.getCanvas()
        while 1:
            self.c.move('zugtag',5,0)
            self.x = self.x + 5
            time.sleep(100)
            print "Bewegung um 5"
            if self.x == 100:
                break
            
            
    def zugSetzen(self,canvas):
        zug1 = PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/Zug.gif")

        return zug1

    def setZugKoordinaten(self, x, y):
        self.x = x
        self.y = y

print "hallo1"
s = Spiel()                 #Starten des Spiels
print "hallo2"           
deets

Da ist noch so einiges im argen, auch wenn du schon Fortschritte gemacht hast.

Im Hintergrund die Breite immer wieder aus self.hintergrund1 zu holen, auf self.hwidth zu speichern und das dann zurueckzugeben ist sinnlos. Entweder berechnest du das einmal, und gibst dann nur den Attribut-Wert zurueck. Oder gleich den Wert von self.hintergrund1.

Und man numeriert auch keine Variablen-Namen durch, das ist immer ein zeichen dafuer, dass man was falsch macht - entweder sollte man eine Liste benutzen, oder bessere Namen ausdenken.

Aber eigentlich ist die ganze Klasse ziemlicher Mist: stattdessen lieber so:

Code: Alles auswählen

class Hintergrund(object):

   def __init__(self):
         self.image = PhotoImage(...)
         self.width = self.image.width()
         self.height = self.image.height()

Das war's schon.

In Zug ist das self.c fuer den Canvas ebenfalls unnoettig - du benutzt den ja nur innerhalb der Methode, warum bindest du das an das Objekt?

canvas = self.grafik.getCanvas() reicht.

Bzw. gleich besser self.grafik.canvas, wie schon mehrfach erwaehnt: getter macht man in Python nicht.

Und zugSetzen ist dann auch voellig quer: zum einen laedst du ein Bild immer wieder neu, statt einmal im Konstruktor. Zum anderen erwartest du da dann mit einem mal den Canvas als Argumennt - obwohl du in fahren den Canvas selbst holst. Das macht doch keinen Sinn. Entweder uebergibt man einen Canvas, oder man holt in sich aus der im Objekt gespeicherten Grafik.

setZugKoordinaten ist auch nicht gut. Initiale Koordinaten solltet du bei Konstruktion uberegeben. Nicht danach irgendwann mal.

Dann ist time.sleep nicht moeglich zu benutzen - denn das friert die GUI ein. Benutze bitte wie schon von mir erwaehnt die "after"-Funktion von tkinter.

Sternchen-Importe hast du auch immer noch.
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Mit "from time import *" holst du alle Funktionen aus dem Modul time, das Modul time beinhaltet eine Funktion time auf die du dann mit time.sleep() zugreifst. Das geht nun leider nicht, da es ja dank deines sternchen import die time Funktion und nicht das Modul ist.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Keine Lust das jetzt alles durchzulesen, aber aus

Code: Alles auswählen

self.gleise = [0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23]
wird

Code: Alles auswählen

self.gleise = range(24)
Magic!

Und die Ein-Buchstaben-Namen finde ich furchtbar. Nein warte, FURCHTBAR.... ok, nocht ein Versuch: FURCHTBAR. Hoffe du merkst wie schlimm das ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

danke dass mir so energisch geholfen wird :)

Für Sachen wie Sternchen Importe, Getter/Setter-Methoden und ein-Buchstaben-Namen entschuldige ich mich, allerdings bin ich noch Schüler und kein Python-Profi, weshalb sich meine Anforderungen an die "Reinheit" des Codes wahrscheinlich etwas von euren unterscheiden. Natürlich ist es gut und wichtig einen ordentlichen Code zu haben, aber da der Schwerpunkt meiner Facharbeit auf der Arbeit selber und nicht auf dem Code liegt, werde ich nicht versuchen die "perfekte" Variante zu schreiben!

trotzdem werde ich jetzt mal das Vorgeschlagene einbauen und die Bewegungung mittels der after-Methode machen, ihr hört sicher wieder bald von meinen Problemen :D


Edit: die durchnummerirung der Variablennamen....ich hab die eine nur hintergrund1 genannt, da mal mehrere Level geplant waren
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Bonsai hat geschrieben:Für Sachen wie Sternchen Importe, Getter/Setter-Methoden und ein-Buchstaben-Namen entschuldige ich mich, allerdings bin ich noch Schüler und kein Python-Profi, weshalb sich meine Anforderungen an die "Reinheit" des Codes wahrscheinlich etwas von euren unterscheiden. Natürlich ist es gut und wichtig einen ordentlichen Code zu haben, aber da der Schwerpunkt meiner Facharbeit auf der Arbeit selber und nicht auf dem Code liegt, werde ich nicht versuchen die "perfekte" Variante zu schreiben!
Das mag ja sein, aber wenn du unsere Tipps geflissentlich ignorierst, dann wirst du auf lange Sicht niemanden finden der die Helfen mag, weil es wirkt dass du die Sachen mit Absicht ignorierst. Und seien wir mal ehrlich, wie viel Aufwand ist es für dich die Sachen umzubenennen? 2 Minuten? 3?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
deets

Bonsai hat geschrieben: Edit: die durchnummerirung der Variablennamen....ich hab die eine nur hintergrund1 genannt, da mal mehrere Level geplant waren
Eben, dann waere das die falsche Herangehensweise: stattdessen wuerdest du eine Liste von Hinterngruenden + einen aktiven Index benutzen. Aber einen Namen einer Variable zu numerieren ist nahezu 100%ig falsch.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Bonsai hat geschrieben:Für Sachen wie Sternchen Importe, Getter/Setter-Methoden und ein-Buchstaben-Namen entschuldige ich mich, allerdings bin ich noch Schüler und kein Python-Profi, weshalb sich meine Anforderungen an die "Reinheit" des Codes wahrscheinlich etwas von euren unterscheiden. Natürlich ist es gut und wichtig einen ordentlichen Code zu haben, aber da der Schwerpunkt meiner Facharbeit auf der Arbeit selber und nicht auf dem Code liegt, werde ich nicht versuchen die "perfekte" Variante zu schreiben!
Im Endeffekt machst du damit einen Fehler. Du machst es anderen schwer dein Programm zu lesen und du machst es dir selber schwer dein Programm zu verstehen und unter Kontrolle zu behalten.
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

@Leonidas, deswegen hab ich auch schon alles verbessert!

Wie ist das eigentlich mit dem Sternchenimport bei tkinter, ich will doch das komplette Modul haben, also ist doch in dem Fall der Sternchenimport richtig, weil wenn ich jede Methode einzeln von Tkinter importiere, werde ich ja nicht mehr froh? :?:
deets

Doch, wirst du immer noch. Zum einen hast du nur sehr wenig von Tkinter wirklich importiert. Und zum zweiten ist es sonst sehr unklar, was woher kommt, bzw. du laeufst Gefahr, Namen aus verschiedenen Modulen zu importieren, und dann kracht's.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du sollst ja auch nicht bem Import der Tkinter-Funktionen alle explizit aufführen. Das wäre natürlich kontraproduktiv und würde auch irgendwann den Namensraum zumüllen. Bei Tkinter hat sich eigentlich der Import der Form

Code: Alles auswählen

import Tkinter as tk
durchgesetzt, auf Elemente aus dem Modul kannst du dann nach dem Muster

Code: Alles auswählen

canvas = tk.Canvas(...)
zugreifen. Dann siehst du woher ein Namen kommst und hast kaum nennenswerten Schreibaufwand.
Das Leben ist wie ein Tennisball.
Bonsai
User
Beiträge: 17
Registriert: Montag 20. August 2012, 10:25

So, mein letzter Stand für heute, bin gespannt was noch alles "unsauber" ist :)

Zurzeit habe ich das Problem, dass mir nicht wirklich klar ist, ich ich in meinem Fall die after_cancel Methode benutzen kann. Laut der definition (after_cancel(id)) muss man ja als ID den Rückgabewert der after-Funktion übergeben. Aber ich habe ja keinen Rückgabewert bzw. kann ihn nicht in einer Variable speichern, außerdem würde ich diese dann nach der after_cancel erst definieren!?

pS: gibt es hier im Forum sowas wie einen Spoiler? Dann wären die Posts nicht so unübersichtlich...

Code: Alles auswählen

# -*- coding: cp1252 -*-

import Tkinter as tk                   #verwendete GUI: Tkinter

#Klasse zur Steuerung des Spiels
class Spiel:
    def __init__(self):
        self.g = Grafik(self)
        
#Klasse zur Abbildung von Objekten auf dem Canvas
class Grafik:
    def __init__(self, spiel):
        self.spiel = spiel

        #Tkinter-Interface
        fenster = tk.Tk()
        
        #Erzeugen eines Hintergrundobjekts
        self.h=Hintergrund()
        
        #Canvas
        self.canvas = tk.Canvas(width=self.h.width,height=self.h.height)
        self.canvas.pack()
        print "Canvas created"
        
        #Hintergrund
        self.hintergrund = self.h.hintergrund
        self.canvas.create_image(0,0,image=self.hintergrund,anchor=tk.NW)

        #Zug
        self.zug_X = 0
        self.zug_Y = 138
        self.z=Zug(self, self.zug_X, self.zug_Y)
        self.zug = self.z.zug
        self.canvas.create_image(self.zug_X,self.zug_Y,image=self.zug,anchor=tk.NW,tags='zugtag')
        self.z.fahren()

        ###########################################
        #wird noch ausgelagert in eigene Klasse
        self.gleise = range(24)
        for i in range(23):
            self.gleise[i] = tk.PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/gleis.gif")
            self.canvas.create_image(i*20,169,image=self.gleise[i],anchor=tk.NW)
        ###########################################
        
        fenster.mainloop()

#Klasse für die Hintergrundobjekte        
class Hintergrund:
    def __init__(self):
        self.hintergrund = tk.PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/hintergrund2.gif")
        self.width = self.hintergrund.width()
        self.height = self.hintergrund.height()
        
#Klasse für den fahrenden Zug
class Zug:
    def __init__(self, grafik, x, y):
        self.grafik = grafik
        self.x = x
        self.y = y

        self.zug = tk.PhotoImage(file = "C:/Users/Manuel/Schule/Informatik_Seminar/Zug.gif")

    def fahren(self):
        canvas = self.grafik.canvas
        canvas.move('zugtag',1,0)
        self.x = self.x + 1
        print "Bewegung um 1"
        if self.x == 10:
            canvas.after_cancel(id)
        canvas.after(10, self.fahren)

print "hallo1"
s = Spiel()                 #Starten des Spiels
print "hallo2"         
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

``self.g`` und ``self.h``, auf das du gefühlte 27 mal hingewiesen wurdest und es immer noch ignorierst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
deets

Schon besser. Aber immer noch snafus drin:

- statt self.z solltest du das Zug-Objekt auch self.zug nennen. Und die 3 Zeilen danach gehoern *IN* das Zug-Ojekt, denn dann weiss doch selbst, wie es zu malen ist etc. Statt da jetzt sinnlos Werte rauszuklauben.

- gewoehn dir mal bitte ab, alles, was du irgendwie benutzt, auf self.* zuzuweisen. Wie self.zug in deinem jetzigen Code. Du brauchst das nur einmal danach - und nicht spaeter nochmal als Instanzattribut.

- BlackJack hat's schon gesagt, und ich wiederhole es: in Python initialisiert man Listen nicht vor. Mach stattdessen

Code: Alles auswählen

gleise = []
for i in xrange(23):
     gleise.append(tk.PhotoImage(...))
Mal ganz abgesehen davon, dass du nicht 23 mal dasselbe Bild laden musst. Da reicht einmal, und dann 23 verschiedene Positionen.

- es ist immer ungeschickt, im *Konstruktor* (also __init__) etwas zu tun, dass den Programmfluss anhaelt. So wie dein Aufruf von fenster.mainloop(). Stattdessen solltest du diese *eine* lokale Variable, die sich wirklich lohnen wuerde auf dem Objekt zu speichern mittels self.fenster = fenster sichern, und dann eine Methode "mainloop" machen, die an self.fenster.mainloop() delegiert.

Bitte *NICHT* grafik.fenster.mainloop() aufrufen! Das verletzt das Gesetz von Demeter.
Antworten