Namensräume nutzen ?

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
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 3. Juli 2008, 23:02

Hallo,

ich habe eine Klasse programmiert und als eigenständiges
Modul gespeichert. Der Zugriff IM hauptprogram nach
import des Moduls funktioniert auch. In dieser Klasse sollen
später alle Attribute und Berechnungen zu meinem Objekt
erfolgen.

An Stelle des Hauptprogramms möchte ich nun ein weiteres
Modul codieren. In diesem soll dann die grafische Oberfläche
erstellt werden.

Wie kann ich nun innerhalb dieses Moduls auf die Instanzen
meiner Klasse zugreifen ?

die übliche Form :

instanz.attribut (self)

klappt leider nicht.

Besten Dank vorab


Kai
imac
20 Zoll
2,4 ghz
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Freitag 4. Juli 2008, 00:22

Ich hab jetzt nicht genau verstanden, wie das Ganze jetzt aufgebaut ist.
Du hast ein Hauptprogramm, welches das Modul (Deine Klasse) importiert.
Und jetzt willst du noch ein weiteres Modul erstellen und in diesem auf die Instanzen der Klasse des anderen Moduls zugreifen?
Wenn du die Instanzen aus dem Hauptprogramm benutzen willst, denke ich gar nicht.
Aber warum erstellst du nicht einfach eine Instanz der Klasse des anderen Moduls und verwendest diese dann?
Wie gesagt, ich weiß nicht genau, was du _genau_ meinst, weil der Text für mich ein wenig verwirrend ist.
DasIch
User
Beiträge: 2435
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Freitag 4. Juli 2008, 01:41

Wieso willst du überhaupt Logik und GUI in Module auslagern die vom Hauptprogramm geladen werden? Das macht das ganze imho unnötig kompliziert. Wenn du die Logik sinnvoll geregelt hast kannst du doch mit der GUI auf diese zugreifen?
Sollte das aus irgendeinem Grund nicht gehen wäre es vielleicht sinnvoll einfach mal zu erklären was du überhaupt erreichen willst.
BlackJack

Freitag 4. Juli 2008, 06:00

Kleines Quelltextbeispiel wäre nicht schlecht.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Freitag 4. Juli 2008, 06:17

so weit schon einmal vielen Dank :

ich habe eine Klasse Panzer, die in einem Modul codiert ist :


class Panzer (object) :

def __init__ (self,panzername,pal,par,pav,pah,pat,pil,pir,piv,pih,pit,
gehen,laufen,
waffe1) :

#Panzerung Übergibt den Startwert der einzelnen Panzerpunkte

self.panzername = panzername
self.pal = pal
self.par = par
self.pav = pav
self.pah = pah
self.pat = pat
self.pil = pil
self.pir = pir
self.piv = piv
self.pih = pih
self.pit = pit

#Bewegung übergibt die Möglichkeiten der Bewegung gehen und laufen

self.gehen = gehen
self.laufen = laufen


#Waffen übergibt ein dictionary x=Waffenname : y=position intern

self.waffe1 = waffe1


#Methoden/Funktionen

def hitzebew (self,bewegung) :
if bewegung is 0 : return 0
elif bewegung >=1 and bewegung < 4 : return 1
else : return 2

def vorgabebew (self,felder) :
if felder in (0,1,2) : return 0
elif felder in (3,4,5) : return 1
else : return 2


( .... die noch nicht fertig ist)

Und die GUI möchte ich ebenfalss in einem Modul aufbauen.
Und hier dann die Namen der Klasse Panzer nutzen.
z.b. um den Wert eines Attributs der Klasse Panzer in der
GUI auszugeben :

from Tkinter import *
from Panzer import *

bewegung = Tk()

bewegung.label = Label(bewegung, text = "tiger.panzername")
bewegung.config(bg="red")
bewegung.label.pack()

bewegung.mainloop()



print fensterbewegung.pal



das funktioniert aber leider nicht.


Gruß
Kai
imac
20 Zoll
2,4 ghz
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Freitag 4. Juli 2008, 07:32

Code bitte in Code-Tags, dann bleibt sogar die Einrückung...und man kann es vielleicht auch lesen!
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Freitag 4. Juli 2008, 07:55

Hi!
derkai hat geschrieben:

Code: Alles auswählen

class Panzer (object) :

    def __init__ (self,panzername,pal,par,pav,pah,pat,pil,pir,piv,pih,pit,
                  gehen,laufen, 
                  waffe1) :

#Panzerung Übergibt den Startwert der einzelnen Panzerpunkte

        self.panzername = panzername
        self.pal = pal
        self.par = par
        self.pav = pav
        self.pah = pah
        self.pat = pat
        self.pil = pil
        self.pir = pir
[...]
Erstens wäre hier aus meiner Sicht ein Dictionary mehr als angebracht. Das spart zum einen Code, der die Referenzen nur in den Namensraum der Klasse schaufelt und zum anderen können die Konfigurationen mehrerer Panzer einfacher importiert (aus Dateien, Datenbanken, ...) und gehandhabt werden.

Code: Alles auswählen

class Panzer (object) :

    def __init__ (self,panzername, panzerwerte, gehen,laufen, waffe1) :

#Panzerung Übergibt den Startwert der einzelnen Panzerpunkte

        self.panzername = panzername
        self.panzerwerte = panzerwerte
[...]
Dann kannst Du die Werte variabel gestalten:

Code: Alles auswählen

schluessel = "pal", "par", "pav", "pah", "pat", "pil", "pir", "piv", "pih", "pit"
werte = xrange(10)     # Daten z.B. aus Datei
panzerwerte = dict(zip(schluessel, werte))
Das Dictionary kannst Du evtl. auch auf die anderen Parameter ausweiten.

Zweitens: was spricht dagegen, dass Du die GUI Klasse von der Logik-Klasse ableitest? Dann hast Du den Code getrennt, kannst aber bei der Erzeugung der GUI (speziell der callbacks) über self direkt auf die Methoden zugreifen.

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Freitag 4. Juli 2008, 08:37

derkai hat geschrieben:
bewegung.label = Label(bewegung, text = "tiger.panzername")
Wenn du den Inhalt von `text` in Anführungszeichen setzt, kann es schon mal gar nicht klappen. Ansonsten muß der GUI natürlich eine Panzer-Instanz namens `tiger` bekannt sein. Eine solche erzeugst du durch

Code: Alles auswählen

import panzermodul
tiger = panzermodul.panzer(....)
Wahrscheinlich wäre es aber empfehlenswert, statt einer einfachen Variable ein Dict oder eine Liste zu verwenden, da es ja vermutlich nicht bei dem einen Panzer bleiben wird.
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Freitag 4. Juli 2008, 09:09

Michael Schneider hat geschrieben:Zweitens: was spricht dagegen, dass Du die GUI Klasse von der Logik-Klasse ableitest? Dann hast Du den Code getrennt, kannst aber bei der Erzeugung der GUI (speziell der callbacks) über self direkt auf die Methoden zugreifen.
Erfahrungsgemäß ist es aber in manchen Fällen zweckmäßiger, die Logik-Klasse von der GUI-Klasse abzuleiten. Denn die callbacks kann man schon an die Widgets binden, wenn sie noch gar nicht definiert sind (look-ups erst bei Aufruf).

Also z.B.:
Tkinter.Frame => PanzerGUI => Panzer

Gruß,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Freitag 4. Juli 2008, 09:15

@Michael:

Was du da praktizierst, ist nicht gerade das, was allgemein unter Trennung von GUI und Logik verstanden wird. Vor allem, wenn du die Logik von der GUI ableitest verbaust du dir auch eine elegante Möglichkeit, die GUI einfach auszutauschen. Ich denke, das ist keine sonderlich sauberer Stil. Aber gut, viele Wege führen nach Rom, und wenn du damit klarkommst und andere sich hinterher nicht mit der Wartung herumschlagen müssen, warum nicht ?
BlackJack

Freitag 4. Juli 2008, 11:33

@Michael: Das ist genau die falsche Reihenfolge der Vererbung. Selbst andersherum gibt es noch Gründe das nicht zu tun. Zum Beispiel wenn man einen Spielstand speichern möchte, kann man in beiden Fällen nicht `pickle` benutzen ohne GUI-Kram mit zu speichern, der ja eigentlich nicht zum inneren Zustand des Spiels gehört.

Und wie testest Du Objekte in Deiner Vererbungsreihenfolge automatisiert ohne das man die GUI braucht?

@derkai: *-Importe sind Böse™.

``is`` darf man nur verwenden, wenn man auf die Objektidentität vergleichen will, was sehr selten ist und in der Regel nur Singletons betrifft. Zahlen sind keine (garantierten) Singletons, also kann ein ``x is 0`` falsch sein, auch wenn `x` den Wert 0 hat.
lunar

Freitag 4. Juli 2008, 14:06

Michael Schneider hat geschrieben:Erfahrungsgemäß ist es aber in manchen Fällen zweckmäßiger, die Logik-Klasse von der GUI-Klasse abzuleiten.
Das ist keine Trennung, sondern vielmehr unmittelbare Kopplung zwischen GUI und Logik durch Vererbung. Eine Trennung ist über Vererbung nur möglich, wenn man Logik- und GUI-Klasse über Mehrfachvererbung in einem Typ zusammenführt. Das ist allerdings eher ungebräuchlich, weil es dazu verleitet, in der Logik-Klasse Annahmen über die GUI zu treffen und die Klasse so doch wieder implizit zu koppeln.

Normalerweise trennt man GUI und Logik durch eine gerichtete, unidirektionale Assoziation, sprich, die GUI-Klasse hält eine Referenz auf ein Objekt der Logik-Klasse in einem Attribut, greift auf dessen Attribute zu und zeigt die Rückgabewerte an. Darüber ist die Logik komplett von der GUI entkoppelt.

Bei manchen Frameworks kann man auch sagen, dass Vererbung und Assoziation ineinander spielen. Die GUI wird im Designer entworfen, und daraus dann eine reine GUI-Klasse erzeugt. Diese wird über Mehrfachvererbung dann mit einem Widget verbunden und mit Verhalten versehen, dass die assozierte Logik-Klasse aufruft und deren Rückgabewerte dann entsprechend aufbereitet und anzeigt. So zumindest sieht das in PyQt4 aus.

Von Verberung, bei der die Logik-Klasse von der GUI-Klasse abgeleitet wird, habe ich glücklicherweise noch nie was gehört ;)
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Freitag 4. Juli 2008, 16:58

so, nun bin ich total doof geworden - trotzdem schon einmal vielen Dank.
es soll in "Textform" so aussehen, dass es später mehrere Panzer auf einem Spielbrett geben soll.

Ich dachte mir halt, dass ich wegen der Übersichtlichkeit möglichst viele Module machen sollte. Daher stammte auch die Idee eine Klasse "Panzer" zu erstellen (Modul Panzer) um dann, wenn die Spieler die Anzahl und Art der Panzer gewählt haben, schnell mehrere Instanzen davon zu erstellen.

Da jeder Panzer bestimmte Eigenschaften hat, also auch viele viele Variabeln.

Dieser Panzer wird später in einer grafischen Oberfläche gesteuert und auf einer Spielfläche bewegt.
Der kann sich dann bewegen, schiessen und viele weitere Dinge tun.

Wie geht man denn dann nun am besten vor, wenn man von Programmieren so wenig Ahnung hat wie ich ?
Bevor jetzt alle glauben, dass ich das eh nicht hinbekommen werde "DOCH"

Es ist halt nur so, dass ich lese, lese und lese und halt irgendwann auch mal mit der Praxis beginnen muss.

Und dies möchte ich halt schon gerne an MEINEM Projekt üben.

Guß
Kai
Zuletzt geändert von derkai am Freitag 4. Juli 2008, 17:06, insgesamt 1-mal geändert.
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Freitag 4. Juli 2008, 17:05

ach so, noch etwas zur gui. Es ist natürlich so, dass je nachdem, auf welchem Feld sich der Panzer befindet, es Rückmeldungen an die Logik (was immer ihr auch damit meint) geben muss.

BSP 1
Der Panzer kann sich 3 Felder weit bewegen. Die Felder sind Hexfelder, also Felder mit 6 Seiten. Eine Drehung des Panzers verbraucht 1 nen Bewegungspunkt. Ebenso ,wenn der Panzer um ein Feld weit bewegt wird.

BSP 2
Neben der Spielfläche soll ein Fenster entstehen. Ein Pfeil nach oben, links und rechts. Durch Anklicken der Buttons, soll sich dann der Panzer "nach links drehen" und die Möglichkeit der Bewegung von drei auf zwei gekürzt werden.

nochmal Kai
imac
20 Zoll
2,4 ghz
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Freitag 4. Juli 2008, 17:17

Dann mußt du in der Logik entsprechende Schnittstellen (Methoden oder Attribute) schaffen, über die die Oberfläche der Logik mitteilen kann, daß sich etwas geändert hat. Die Logik kannst du dir als eine schwarze Kiste mit vielen Knöpfen und Schlitzen (Eingabe) und Anzeigen und "Druckern" (Ausgabe) vorstellen. Die Oberfläche bekommt so einen Kasten in die Hand gedrückt und muß jetzt sehen, daß sie nur über die bereitgestellten Schnittstellen die Kiste so steuert, wie es gewünscht ist.

Prinzipiell ist dein Ansatz einer eigenen Klasse für die Panzer genau richtig. Vermutlich würde es sich auch anbieten, eine (Logik-) Klasse für die Eckdaten des Spielfeldes zu erstellen, in der es eine Liste gibt, in der alle auf dem Spielfeld befindlichen Einheiten verzeichnet sind.

Als nächste Schicht kommt dann die Oberfläche, der du eine Instanz der Spielfeldklasse bekannt machst, über die sie das Spiel dann steuern kann. Diese Spielfeldklasse ist gewissermaßen die Hauptklasse des Logikteils, die o.g. schwarze Box.
Antworten