Objekt sich selbst ersetzen lassen?

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
chuck
User
Beiträge: 2
Registriert: Dienstag 3. April 2012, 15:42

Hallo,

ich bin relativ neu in Python (und ganz neu im Python-Forum) und habe eine kleine (hoffentlich einfache) Frage, ob ich in Python ein Klassen-Objekt sich selbst ersetzen lassen kann?

Die Sache ist die, dass ich eine globale Liste anlege, in die sich neue initialisierte Objekten eintragen sollen, falls dort noch kein Objekt mit dem eigenen 'Namen' existiert. Falls doch, soll das neue (nun temporaere) Objekt sich selbst durch das existeirende ersetzen/referenzieren.

Code: Alles auswählen

dingsList = []
class dings(object):
    def __init__(self):
        self._dings = "" 
    def getDings(self):
        return self._dings
    def _findDings(self,dingsName):
        dings = None
        # oder glecih was mit filter...?
        for dingsIter in dingsList:
            if dingsIter.getDings() == dingsName:
               dings = dingsIter 
        return dings
    def setDings(self,dingsName):
        self._dings = dingsName
        existingDings = self._findDings(self._dings)
        if not existingDings:
            dingsList.append(self)
        else:
            # so nicht, aber wie dann?
            self = existingDings

self = existingDings funktioniert ja nicht, aber kann ich irgendwie anders das Objekt umreferenzieren, i.e. den Pointer umbiegen...?
Ein 'externer' Abgleich der Objekte in der Liste waehrend der Initialisierung eines neuen Objekts ginge natuerlich auch, aber imho waere es schon nett, wenn man es 'intern' gleich abhandeln koennte ;)

Ich hoffe, dass ich mein Problem halbwegs verstaendlich rueberbringen konnte -- ueber alle Tipps und Ideen bin ich dankbar.

Gruesse -- Thomas
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du musst das Objekt aus der Liste löschen und das aktuelle in die Liste integrieren. Das könnte man z.B. mit `list.pop` und `list.insert` erledigen.

Es bleibt die Frage: Wozu? Vor allem, wenn es sich um eine globale Liste handelt. Mit globalen Variablen brockt man sich eigentlich mehr Ärger ein, als dass sie Probleme lösen.

Vielleicht beschreibst Du uns doch genereller, was Du eigentlich für ein Problem lösen willst. Evtl. kann man das mit Klassenattributen besser lösen, oder man nutzt ein `set` und baut seine Objekte entsprechend auf, oder oder ...

Generell sind Getter und Setter in Python unüblich. Für komplexere Logik beim Abfragen oder Setzen von Werten benutzt man Properties. Mehr dazu solltest Du in der Doku bei der Built-In-Funktion `property` finden. Bei Klassen gibt es dazu dann hübsche Dekoratoren:

Code: Alles auswählen

class Foo(object):

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        return self._bar * 2

    @bar.setter
    def bar(self, value):
        self._bar = value - 1
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Das Problem ist schon loesbar wie gedacht, naemlich mittels __new__ - diese Methode eine Klasse wird *vor* der Konstruktion und Initialisierung (__init__) aufgerufen, und kann tatsaechlich eine existierende Instanz zurueckliefern. Damit laesst sich ein parametrisiertes Singleton bauen.

Code: Alles auswählen


class Foo(object):

    INSTANCES = {}

    def __new__(cls, name):
        if name in cls.INSTANCES:
            return cls.INSTANCES[name]
        return object.__new__(cls)


    def __init__(self, name):
        self.INSTANCES[name] = self



a = Foo("a")
print id(a)
b = Foo("b")
print id(b)
c = Foo("a")
assert id(c) == id(a)
Aber zwei Anmerkungen:

- deine Liste ist wahrscheinlich die falsche Datenstruktur, wenn es dir um einen Namensbasierten lookup geht! Darum habe ich ein dict gewaehlt.
- das ist schon alles ein bisschen magisch. Nix dagegen einzuwenden, wenn man's wirklich braucht. Darum auch von mir die Frage: wozu denn?
chuck
User
Beiträge: 2
Registriert: Dienstag 3. April 2012, 15:42

Prinzipiell will ich eine Hierarchie von mehreren Elementebenen Aufbauen, mit den 'atomaren' Einheiten als den zentralen Objekten (die globale Liste will ich eigentlich zur nachtraeglichen Ordnung benutzen.

ich versuche das mal in etwas Pseudocode anzudeuten:

dem elementaren Objekt

Code: Alles auswählen

atomList = []
class atom(object):
    def __init__(self):
...
    def setAtom(self,atomName):
        self._atom = atomName
    def setMolecule(self,moleculeName):
        self._molecule = molecule()
        self._molecule.setMolecule = moleculeName

Code: Alles auswählen

moleculeList = []
class molecule(object):
    def __init__(self):
...
    def setMolecule(self,moleculeName):
        self._molecule = moleculeName
    def setCluster(self,clusterName):
        self._cluster = cluster()
        self._cluster.setCluster = clusterName

Code: Alles auswählen

clusterList = []
class cluster(object):
...
idealerweise sollte ich vermutlich eine Basisklasse fuer meine hierarchischen Ebenen entwerfen, von denen die einzelnen dann erben, allerdings haben die verschiedenen Ebenen am Ende auch verschiedene Eigenschaften.
Wie auch immer: ich moechte von einem atomaren Element ausgehend die hoeheren Ebenen setzen; falls nun noch ein weiteres atomares Element dazu kommt, fuer das schon eine der hoeheren Ebenen angelegt wurde, soll es sich dann daran moeglichst transpararent 'haengen'.
Und wenn das steht, wollte ich mich daran wagen, die Tochterobjekte in einer Ebene iterabel zu machen ;)


vielleicht denke ich auch etwas zu kompliziert ;)
BlackJack

@chuck: Ich weiss nicht ob ich es richtig verstehe aber „transparent” klingt für mich hier „magisch”. Warum erstellst Du nicht Objekte die sich explizit um die Verwaltung der Menge von Atomen, Molekülen, und Clustern kümmern? Globale Listen (oder allgemein Container) wo automagisch alle Exemplare eines Typs eingetragen werden, sind IMHO keine gute Idee. Man kann dann nicht mal eben so solche Exemplare erstellen, ohne dass man globalen Zustand im Programm verändert. Das ist zum ausprobieren oder für Unittests schlecht.
Antworten