Objekte dynamisch erstellen

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.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

sorry für den wenig aussagekräftigen Titel, aber viel mehr viel mir zu meinem Problem nicht ein. Auch weiss ich nicht genau nach welchen Stichworten ich suchen soll - somit bleib meine Suche ziemlich ergebnislos.

Bisher habe ich immer wenn ich Objekte erstellen wollte und nicht wusste wie viele es einmal werden sollen eine Liste erstellt und Objekte angehängt. Dieses Mal hätte ich das ganze gerne genau anders herum. Ich weiss vorher wie viele Objekte ich gebrauchen werde und ich möchte diesen Objekten jeweils einen eigenen Namen geben damit ich sie später direkt ansprechen kann. Zusätzlich möchte ich sie gerne möglichst einfach alle nacheinander ansprechen können. Ich dachte dabei an eine Variante die vielleicht so ausschauen würde:

Code: Alles auswählen

class OBJ1(object):
    def __init__(self):
        self.name = "Objekt 1"

    def test(self):
        return self.name
    
class OBJ2(object):
    def __init__(self):
        self.name = "Objekt 2"

    def test(self):
        return self.name
  
def main():
    objects = {"test": "OBJ1",
               "nochntest": "OBJ2"}
    
    for obj in objects:
        obj = objects[obj]

    
    for obj in objects:
        print locals[obj].test()

   
if __name__ == "__main__":
    main()
Naja - mir ist schon klar das die Mainfunktion nicht funktioniert - ich stehe halt ein wenig auf dem Schlauch. Ich hatte schon einie Variante mit ``eval()`` im Netz gefunden und auch probiert, doch lese ich hier häufiger das man schön die Finger von ``eval()`` lassen soll - was ich bisher auch immer so gesehen habe.
Also: Wie kann ich so was realisieren?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Das ist aber ziemlich verworren. Vielleicht beschreibst du mal, was du eigentlich erreichen willst. Möglicherweise ist der richtige Weg zum Ziel ein ganz anderer.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Hi,
das Problem ist ich habe einen Haufen Objekte - die erben alle von einer Klasse. Nun werden diese Objekte alle erst einmal erstellt. Danach gibt es mindestens 3 Fälle in denen ich auf eine gemeinsame Methode von allen diesen Objekten zugreifen muss. Das ist ergibt mehrere Haufen Code in denen immer nur das gleiche steht- halt der Zugriff auf eben diese Methoden von dem Haufen Objekten.
Da muss ich dann aufpassen das ich keinen Aufruf eines Objektes vergesse. Möchte ich später aus welchen Gründen auch immer noch ein zusätzliches Objekt von meiner Mutterklasse ableiten und mit aufnehmen muss ich die ellenlangen Listen mit den Aufrufen für immer dieselbe Methode erweitern.

Ich würde das ganze halt gerne vereinfachen indem ich alle Objekte mit den Klassennamen und Dem Objektnamen nur einmal aufnehmen muss und danach über ein iterable auf alle Objekte nacheinander zugreifen kann.

Ist das ein wenig verständlicher?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Lonestar hat geschrieben:Ist das ein wenig verständlicher?
Also mir ist nicht verständlich, was in diesem Fall gegen eine Liste spricht.

Code: Alles auswählen

my_objects = list()
for i in xrange(5):
    my_objects.append(MyClass())

# iterieren über alle Objekte
for obj in my_objects:
    obj.my_method()

# Eindeutig identifizieren kannst du ein Objekt über den Index:
my_objects[2].my_attr = 0
Anforderungen, die gegen diese Lösung sprechen, sehe ich keine...
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Lonestar hat geschrieben:das Problem ist ich habe einen Haufen Objekte - die erben alle von einer Klasse.
Um deine Verwirrung aufzulösen: Objekte erben nicht von Klassen, sondern Klassen erben von Klassen. Klassen definieren die Eigenschaften von Objekten. Man sagt dann, ein Objekt ist eine Instanz / ein Exemplar einer Klasse, oder einfach "ein Objekt der der Klasse SoUndSo". Wenn Klasse B von Klasse A erbt, dann ist ein Objekt der Klasse B auch ein Objekt der Klasse A. Wenn A ein Attribut / eine Methode definiert dann "kennt" das Objekt der Klasse B das ebenso:

Code: Alles auswählen

>>> class A(object):
...     def __init__(self, x):
...         self.x = x
...     def double_x(self):
...         return self.x * 2
...
>>> class B(A):
...     pass
...
>>> o = B(3)
>>> print o.double_x()
6
Den Rest verstehe ich immer noch nicht so ganz.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Meinst du vielleicht sowas?

Code: Alles auswählen

class MyObject(object):
    def __init__(self, name):
        self.name = name
    def test(self):
        return self.name

def main():
    objects = [MyObject("Objekt 1"), MyObject("Objekt 2")]
    for obj in objects:
        print obj.test()
    o1, o2 = objects
    print o1.test()
    print o2.test()

if __name__ == "__main__":
    main()
In specifications, Murphy's Law supersedes Ohm's.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

pillmuncher hat geschrieben: Meinst du vielleicht sowas?
Nein sowas meine ich ganz bestimmt nicht.
Ich merke langsam selber das ich mich oben nicht 100% sauber ausgedrückt habe - hätte aber nicht gedacht da ich so schwer zu verstehen bin. Das oberste Beispiel zeigt nicht genau die Vererbungshierarchie die bei mir vorliegt. Das ganze ähnelt eher folgendem Schema:

Code: Alles auswählen

class BaseObj(object):
    def __init__(self):
        self.name = False

    def test(self):
        return self.name
        
class  OBJ1(BaseObj):
    def __init__(self):
        self.name = "Objekt 1"

    def method1(self):
        pass
        
class  OBJ2(BaseObj):
    def __init__(self):
        self.name = "Objekt 2"

    def double_x(self, x):
        pass
Ich habe also eine Basisklasse. Ich definiere viele andere Klassen (nicht nur 2)die alle von der Basisklasse erben werden. Mir geht es nicht darum auf den Namen zuzugreifen - das ist einfach nur ein vereinfachtes Beispiel.
Wenn ich später die Objekte erstelle möchte ich diese Objekte gerne mit einem Namen ansprechen nicht über einen Listenindex auf sie Zugreifen. Zusätzlich würde ich gerne auf alle erstellten Objekte mit Hilfe einer Schleife zugreifen können.
Momentan würde ich fast dazu Tendieren die Objekte alle in einem Dictionary abzulegen. Dann kann ich auch über einen Namen auf die einzelnen Objekte zugreifen und über alle iterieren - das ist zwar nicht ganz das was ich gerne haben würde wäre aber relativ leicht zu machen...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Lonestar hat geschrieben: Wenn ich später die Objekte erstelle möchte ich diese Objekte gerne mit einem Namen ansprechen
Frage: Was ist für Dich ein "Name"? Erst wenn das klar ist, können wir hier weiter reden.
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Hyperion hat geschrieben: Erst wenn das klar ist, können wir hier weiter reden.
Hi, wenn du den kompletten Satz zitiert hättest würde der Fetzen meiner Meinung nach mehr Sinn ergeben - vor allem da ice2k3 schon vorgeschlagen hat eine Liste zu nehmen. Das fühlt sich fast so an als würdest du mich auf den Arm nehmen wollen.
Seis drum...
wie ich schon schrieb möchte ich die Objekte und deren Methoden über einen Namen und nicht über einen Listenindex aufrufen. Mit Namen meinte ich hier halt den Bezeichner der Variable der die erzeugte Instanz einer Klasse zugeordnet wird

bei

Code: Alles auswählen

class MyClass(object):
    pass

x = MyClass()
wäre x halt ein Name - von mir auch ein Bezeichner oder ein Variablenname
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Lonestar hat geschrieben:
Hyperion hat geschrieben: Erst wenn das klar ist, können wir hier weiter reden.
Hi, wenn du den kompletten Satz zitiert hättest würde der Fetzen meiner Meinung nach mehr Sinn ergeben - vor allem da ice2k3 schon vorgeschlagen hat eine Liste zu nehmen. Das fühlt sich fast so an als würdest du mich auf den Arm nehmen wollen.
Nein! Denn danach schriebst Du etwas von einem Dictionary - und das deutete an, dass Du nicht "Name", sondern "String" meintest... das wollte ich erst einmal geklärt wissen.
wie ich schon schrieb möchte ich die Objekte und deren Methoden über einen Namen und nicht über einen Listenindex aufrufen. Mit Namen meinte ich hier halt den Bezeichner der Variable der die erzeugte Instanz einer Klasse zugeordnet wird

bei

Code: Alles auswählen

class MyClass(object):
    pass

x = MyClass()
wäre x halt ein Name - von mir auch ein Bezeichner oder ein Variablenname
Ok, dann hast Du doch grad die Lösung gepostet. Du bindest eben jedes einzelne Objekt an einen Namen und kannst dann diesen später nutzen, um auf das Objekt zuzugreifen...

... aber mal im Ernst: Wozu? Das riecht doch nach einem falschen Ansatz!

"Dynamisch" und separate "Namen" schließen sich imho aus!
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Lonestar hat geschrieben:Das fühlt sich fast so an als würdest du mich auf den Arm nehmen wollen.
Eher nicht.

Wenn du alle Objekte in einer Liste hast, kannst du doch jederzeit ein Objekt herausholen und ihm einen Namen zuweisen.

Ich verstehe immer noch nicht, wo das Problem ist ....
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

@numerix
ich glaub manchmal sehe ich in letzter Zeit einfach den Wald vor lauter Bäumen nicht... und das nicht nur hier in meiner Freizeit beim Programmieren. Ich glaube das führt zu genau dem Ergebnis das ich suchte...

Code: Alles auswählen

    obj_list = list()
    obj_list.append(MyClass())
    
    test = x[0]
ich hoffe mal ich mache das richtig?
mit ``test`` und ``obj_list[0]`` greife ich beide mal auf das gleiche Objekt zu. Oder erstelle ich irgendwelche Kopien und baue mir damit diverse Fehler ein?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Lonestar hat geschrieben:@numerix
ich glaub manchmal sehe ich in letzter Zeit einfach den Wald vor lauter Bäumen nicht... und das nicht nur hier in meiner Freizeit beim Programmieren. Ich glaube das führt zu genau dem Ergebnis das ich suchte...

Code: Alles auswählen

    obj_list = list()
    obj_list.append(MyClass())
    
    test = x[0]
ich hoffe mal ich mache das richtig?
mit ``test`` und ``obj_list[0]`` greife ich beide mal auf das gleiche Objekt zu. Oder erstelle ich irgendwelche Kopien und baue mir damit diverse Fehler ein?
Nein, das ist das selbe Objekt! So ist es schon richtig. (Ein einfacher Test wäre da auch in ner Shell möglich ;-) )
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Bitte beachte noch, dass das nicht immer gilt. Bei sog. "immutable" Datentypen werden Kopien erzeugt und nicht die Referenz übergeben. Dazu zählen z.B. int, float, str, tuple.
Bei selbst erstellten Datentypen (bzw. Klassen) handelt es sich allerdings immer um "mutable" Typen.
BlackJack

@ice2k3: Warum taucht dieser Blödsinn immer wieder auf!? Objekte funktionieren in dieser Hinsicht *alle* *gleich*! Es sind immer Referenzen, da wird nichts kopiert.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

BlackJack hat geschrieben:@ice2k3: Warum taucht dieser Blödsinn immer wieder auf!? Objekte funktionieren in dieser Hinsicht *alle* *gleich*! Es sind immer Referenzen, da wird nichts kopiert.
Soso:

Code: Alles auswählen

In [1]: i = 1

In [2]: l = [i]

In [3]: l[0] = 2

In [4]: i
Out[4]: 1
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

@ice2k3: Und das soll jetzt was zeigen? Du überschreibst ein Element der Liste. Warum sollte da etwas anderes passieren als das gezeigte Verhalten?

Zwei Gegenbeispiele:

Code: Alles auswählen

>>> d = dict(spam=42)
>>> L = [d]
>>> L[0] = dict()
>>> d
{'spam': 42}
Verhalten analog zu dem von dir gezeigten, Dicts sind aber veränderbar.

Code: Alles auswählen

>>> spam = 'spam' * 1000
>>> L = [spam]
>>> id(spam) == id(L[0])
True
Sowohl das Element der Liste als auch das Objekt, das an den Namen `spam` gebunden ist, haben dieselbe Identität <=> selbes Objekt. Strings sind aber unveränderbar.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

@ice2k3: Mach dir nichts draus.
Ich habe auch eine ganze Weile mit dieser falschen Annahme gut gelebt und es mir so passend zurecht gelegt, dass es (fast) immer gut zusammenpasste. Bis irgendwann mal ein Fall kam, wo es nicht mehr passte. Das habe ich dann im Forum unter Schmerzen gelernt ... :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui :-) Da bin ich aber beruhigt, dass ich hier mal keinen Mist erzählt habe :-)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ice2k3 hat geschrieben:
BlackJack hat geschrieben:@ice2k3: Warum taucht dieser Blödsinn immer wieder auf!? Objekte funktionieren in dieser Hinsicht *alle* *gleich*! Es sind immer Referenzen, da wird nichts kopiert.
Soso:

Code: Alles auswählen

In [1]: i = 1

In [2]: l = [i]

In [3]: l[0] = 2

In [4]: i
Out[4]: 1
Und wo wiederspricht das jetzt BlackJacks Aussage?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten