Zugriff auf Objekt überall im Programm

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
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Hallo!

ich schreibe gerade mit python /pygame ein kleines Jump and run Spiel.

Nun zum Problem:
Ich habe mir eine Art "ressourceLoader"-Klasse geschrieben. diese verwaltet ein dictionary indem alle Graphiken mit Filename abgelegt sind. Will ich nun irgendwo im Programm eine Graphik laden führe ich eine methode dieser ressource-loader klasse aus, die mir die entsprechende graphik aus dem dict zurückgibt.

Sieht folgendermaßen aus:

Code: Alles auswählen

import pygame
import os

class RessourceLoader():
    def __init__(self):
        self.graphicDict = {}

    def load_graphic(self, filename):

        path = os.path.join('..', 'data', 'gfx',  filename)
        try:
            if not path in self.graphicDict:
                self.graphicDict[filename] = pygame.image.load(path).convert_alpha()
        except:
            print("Error while loading graphic: ", path)

        return self.graphicDict[filename]
Das funktionert auch alles wunderbar. Wie kann ich jetzt jedoch überall im gesamten Programm auf dieses ein Objekt der Klasse zugreifen, da bei Programmstart initialisiert wird?
Klar, ich könnte es immer weiter durchgeben als Parameter, doch das macht mir das ganze ein wenig zu unübersichtlich.

Game -> Levelmanager -> Level -> Map -> Sprite -> Animation -> Image(hier wird die methode erst aufgerufen)

Ihr seht das ganze ist ziemlich verzweigt. Und um Hintergrundbilder o.ä. zu laden kann ich ähnliche ketten aufstellen.
So müssten 75% meiner Klassen im gesamten Spiel diesen ressourceLoader als Parameter haben. gefällt mir rigendwie nicht:/

Gibt es eine "schöne" Möglichkeit wie ich bei programmstart ein Objekt erstelle und immer und überall darauf zugreifen kann?
Wie würdet ihr das ganze implementieren?

greetings
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dann initialisiere es doch in _diesem_ Modul und benutze dann die Instanz statt der Klasse.
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Meiner Meinung nach solltest du das nicht mit einer Klasse lösen. Ich würde es als Funktion in einem Modul 'tools' oder 'utils' bereitstellen und dieses Modul dann überall dort importieren, wo du es benötigst.

Nachtrag: Mir fehlt leider ein wenig die Erfahrung mit PyGame, aber willst du wirklich alle Grafiken im Speicher halten? Darauf läuft dein Ansatz mit dem Dictionary ja hinaus. Das kann natürlich Sinn machen, muß aber nicht.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

cofi hat geschrieben:Dann initialisiere es doch in _diesem_ Modul und benutze dann die Instanz statt der Klasse.
Wenn ich in jedem Modul neu Instanziere habe ich ja ejdesmal ein neues grafik-dictionary. Das sollte für das ganze Programm gültig sein.

Pekh hat geschrieben:Meiner Meinung nach solltest du das nicht mit einer Klasse lösen. Ich würde es als Funktion in einem Modul 'tools' oder 'utils' bereitstellen und dieses Modul dann überall dort importieren, wo du es benötigst.
Wenn ich die Funktion einfach ein Modul schreibe, wo soll ich dann das dictionary ablegen?

Meint ihr so in der Art?
Kurz getestet scheint das zu funktionieren, aber nur mit dem global keyworld. Ohne werden neue dicts erstellt.

Code: Alles auswählen

import pygame
import os

self.graphicDict = {}

def load_graphic(self, filename):
    global graphicDict
    path = os.path.join('..', 'data', 'gfx',  filename)
    try:
        if not path in self.graphicDict:
            self.graphicDict[filename] = pygame.image.load(path).convert_alpha()
    except:
        print("Error while loading graphic: ", path)

    return self.graphicDict[filename]
BlackJack

@Sephiroth: Das funktioniert auch ohne ``global`` aber sicher *so* wie's da steht überhaupt nicht. Was soll denn `self` hier sein?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Sephiroth hat geschrieben:
cofi hat geschrieben:Dann initialisiere es doch in _diesem_ Modul und benutze dann die Instanz statt der Klasse.
Wenn ich in jedem Modul neu Instanziere habe ich ja ejdesmal ein neues grafik-dictionary. Das sollte für das ganze Programm gültig sein.
Les den Satz nochmal, genau _das_ meinte ich nicht.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

BlackJack hat geschrieben:@Sephiroth: Das funktioniert auch ohne ``global`` aber sicher *so* wie's da steht überhaupt nicht. Was soll denn `self` hier sein?
War ein copy/paste Fehler die self's
cofi hat geschrieben:
Sephiroth hat geschrieben:
cofi hat geschrieben:Dann initialisiere es doch in _diesem_ Modul und benutze dann die Instanz statt der Klasse.
Wenn ich in jedem Modul neu Instanziere habe ich ja ejdesmal ein neues grafik-dictionary. Das sollte für das ganze Programm gültig sein.
Les den Satz nochmal, genau _das_ meinte ich nicht.
Was meinst du genau mit "_diesem_" Modul?
(In meinem aktuellen Sprachgebrauch setzte ich "Modul" mit ".py-Datei" gleich. Folglich habe ich in meinem Programm recht viele Module. (Von denen sehr viele Zugriff auf dieses dictionary benötigen.) Welches meinst du also mit "_diesem_" Oder hab ich gerasde einen Denkfehler)

Gruß
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das in dem du `RessourceLoader` definierst.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

jop, dann muss ich allerdings an alle anderen Klassen das Objekt als Parameter weitergeben oder gibts noch eine andere Möglichkeit?
Wollte nämlich verhindern das so eine "helfer-klasse" durch das halbe programm gereicht wird
siehe: Game -> Levelmanager -> Level -> Map -> Sprite -> Animation -> Image(hier wird die methode erst aufgerufen)
obwohl sie nur ganz am Ende überhaupt benutzt wird.

ich glaube mittlerweile das ich den Aufbau des Programms etwas umstrukturieren sollte und das Problem irgendwie umgehen sollte, da es wohl kein einfaches Patentrezept gibt so wie ichs mirs vorstelle.

greetings

Edit:
Ok, vergesst was ich gesagt habe. Ich glaube eine Lösung gefunden zu haben.
Ich definiere das dictionarry einfach als statische member variable..
Dann kann ich die Klasse überall neu instanzieren und all instanzen nutzen trotzdem das gleiche dictionarry
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo Sephiroth,

ich glaube, cofi spricht von Singletons. Such einfach mal danach: Du kannst tatsächlich Instanzen von Klassen importieren. Wobei ich immer dachte, das sei eher ein "don't" aber so gut kenne ich mich mit Design-Prinzipien in Python leider nicht aus.

Diese Seite habe ich mir dazu mal gebookmarked - sie ist aber gerade unerreichbar: http://lucumr.pocoo.org/2009/7/24/singl ... -in-python

Gruß,

brb
BlackJack

@Sephiroth: Es war gemeint, dass Du in *einem* Modul ein Exemplar erstellst und dieses *eine* Exemplar dann überall verwendest. Alternativ kann eben auch ein Modul selbst als Singleton herhalten, denn im Normalfall sind Modulobjekte ja Singletons.
Antworten