Klassenobjekt benennen und Namen ausgeben

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
NilsV
User
Beiträge: 30
Registriert: Dienstag 17. August 2010, 12:35

Hallo,

ich beschäftige mich seit ein paar Wochen mit Python (Version 3.1), versuche gerade den Umgang mit Klassen zu verstehen und habe dazu zwei Fragen:

1.
Wie kann ich über print() den Namen des aktiven Klassenobjektes ausgeben lassen?


Der Hintergrund ist das ich beim erstellen eines neuen Klassenobjektes eine Rückmeldung haben möchte, ob wirklich ein neues Klassenobjekt, mit dem richtigen Namen, erstellt wurde (Ich glaube in meinem Übungscode überschreibe ich immer nur ein und das selbe Klassenobjekt.). bisher habe ich es mit

Code: Alles auswählen

print(self)
versucht, das liefert mir etwas das aussieht wie der Speicherblock, in dem das Objekt im Arbeitsspeicher abgelegt ist.


2.
Ich möchte das jedes neue Klassenobjekt im Namen mit einer aufsteigenden Zahl versehen wird (objekt1, objekt2, ...).


Dafür benutze ich einen Integer als Zähler, der bei jedem Aufruf der Funktion zum erstellen eines neuen Objektes um 1 erhöht wird. Dann erzeuge ich einen String mit dem Namen für das neue Klassenobjekt

Code: Alles auswählen

name = 'objekt' + str(zähler)
wie weise ich dem neuen Klassenobjekt nun diesen Namen zu? Normalerweise würde das so gehen

Code: Alles auswählen

objekt1 = Objekte()
aber ich möchte ja gerne meinen String "name" benutzen und

Code: Alles auswählen

name = Objekte()
scheint nicht das zu tun was ich möchte. Sicher bin ich mir da aber nicht, kann es im Moment nicht prüfen (Siehe Frage 1).

Würde mich über Hilfe und ein eine kurze Erklärung warum es wie gemacht wird sehr freuen.

MfG

NilsV
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Zu 1: Das geht nicht. Ein Objekt hat keine Information darueber, an welchen Namen es gebunden ist. Es kann ja auch an mehr als einen Namen gebunden sein, oder nur indirekt in einer Datenstrucktur stecken!

Zu 2: Fuer so etwas verwendet man Listen.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Rebecca hat geschrieben:Zu 1: Das geht nicht. Ein Objekt hat keine Information darueber, an welchen Namen es gebunden ist. Es kann ja auch an mehr als einen Namen gebunden sein, oder nur indirekt in einer Datenstrucktur stecken!
Sicher?
BlackJack

@DasIch: Ich wünschte die Leute würden sich Anfängern gegenüber solche Antworten sparen, nur um anzugeben, dass sie *Implementierungsdetails* kennen. Es ist in Python nicht möglich die Namen herauszufinden, denn die Existenz von `sys._getframe()` darf man nicht als gegeben ansehen. Das Problem ist das Anfänger dazu neigen solche "Lösungen" dann auch tatsächlich zu verwenden, statt es richtig zu machen.
NilsV
User
Beiträge: 30
Registriert: Dienstag 17. August 2010, 12:35

Hi,

vielen Dank für eure Hilfestellungen.

Zu Frage 1:
Wenn das nicht geht ist es ja schon deswegen Sinnvoll eine Liste mit den Namen der Objekte zu führen, um die Objekte über Ihre Namen in der Liste aufrufen zu können.

Parallel zu den tatsächlichen Objekten der Klasse eine Liste der Objekte führen zu müssen erhöht aber auch ganz schön die Fehleranfälligkeit beim Programmieren. Da braucht man nur mal zu vergessen beim Löschen eines Objektes den Eintrag in der Liste zu entfernen und schon endet alles im Chaos. So langsam verstehe ich was es mit versteckten Programmfehlern auf sich hat :wink:

Zu Frage 2:
Jetzt führe ich also eine Liste mit den Objektnamen und füge mit append den Namen für das aktuell zu erstellende Objekt ans Ende der Liste. Aber der Name in der Liste ist immer noch ein String, wie kann ich den benutzen um ein neues Klassenobjekt mit diesem Namen zu erzeugen? Geht das einfach so?:

Code: Alles auswählen

objektNamenListe[-1] = Objekte()
(Die Frage klingt vielleicht Blöd, aber ich kann im Moment nicht Erkennen ob hier wirklich das passiert was passieren soll.)

MfG

NilsV
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

NilsV hat geschrieben:Der Hintergrund ist das ich beim erstellen eines neuen Klassenobjektes eine Rückmeldung haben möchte, ob wirklich ein neues Klassenobjekt, mit dem richtigen Namen, erstellt wurde (Ich glaube in meinem Übungscode überschreibe ich immer nur ein und das selbe Klassenobjekt.).
Ich verstehe nicht ganz was du machen willst. Poste doch mal ein Beispiel. Ich habe das Gefühl das du das Problem irgendwie völlig falsch angehst. Denn die Information die du haben willst braucht man eigentlich nie. Das geht immer anders besser und viel einfacher.

Und zur Nomenklatur: Das was du verwendest nennt sich „Instanz“. Mit „Klassenobjekt“ bezeichnet man die Klasse selbst (in deinem Beispiel ist `Objekte` das Klassenobjekt), die meinst du aber glaube ich nicht.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Okay, wenn du jetzt eine Liste mit Namen fuehrst, solltest du mal ueber ein Dictionary nachdenken. Aber vielleicht beschreibst du mal, was fuer ein Problem du zu loesen versuchst, damit wir dir helfen koennen, den richtigen Loesungsweg zu finden. (Stichwort XY-Problem...)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

@NilsV: Du sollst nicht die "Namen" der Objekte in die Liste stecken, sondern die Objekte *selbst*.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

NilsV hat geschrieben:Aber der Name in der Liste ist immer noch ein String, wie kann ich den benutzen um ein neues Klassenobjekt mit diesem Namen zu erzeugen? Geht das einfach so?:

Code: Alles auswählen

objektNamenListe[-1] = Objekte()
Du kannst auch die Objekte direkt in die Liste schmeissen, wie dein Snippet es zeigt, aber dazu nutzt man

Code: Alles auswählen

objekte.append(Objekt())
dein Snippet haette immer das letzte Objekt ersetzt.
Namen sind in Python nichts anderes als eine Referenz und haben keine andere Bedeutung als den Zugriff, im Besonderen sind das keine Schubladen sondern eher Post-Its. Objekte existieren auch ohne dass ihnen ein Name zugewiesen wird.
NilsV
User
Beiträge: 30
Registriert: Dienstag 17. August 2010, 12:35

Und zur Nomenklatur: Das was du verwendest nennt sich „Instanz“. Mit „Klassenobjekt“ bezeichnet man die Klasse selbst (in deinem Beispiel ist `Objekte` das Klassenobjekt), die meinst du aber glaube ich nicht.
Vielen Dank für den Hinweis. Du hast recht, ich meine Instanzen (Gerade nochmal nachgelesen)
Aber vielleicht beschreibst du mal, was fuer ein Problem du zu loesen versuchst, damit wir dir helfen koennen, den richtigen Loesungsweg zu finden.
Python zu lernen ;) Im moment im speziellen den Umgang mit Klassen. In meiner kleinen Übung erzeuge ich Lampen (lampe1, lampe2, ...) als Instanzen einer Klasse. Die Lampen sollen ein und aus geschaltet werden können und Informationen über den Verbrauch (Watt der Glühbirne) haben.

Die Klasse Lampen:

Code: Alles auswählen

class Lampen(object):
    def __init__(self, watt):
        self.watt = watt
        self.an = False
Im Moment geht es mir erstmal nur darum Lampen mit den entsprechenden Namen zu erzeugen, ohne die Namen (lampe1, lampe2, ...) manuell eingeben zu müßen.

Code: Alles auswählen

Du sollst nicht die "Namen" der Objekte in die Liste stecken, sondern die Objekte *selbst*.
Die Objekte (Instanzen) exestieren noch nicht, die möchte ich gerade erzeugen.
Du kannst auch die Objekte direkt in die Liste schmeissen, wie dein Snippet es zeigt, aber dazu nutzt man

Code: Alles auswählen

objekte.append(Objekt())
dein Snippet haette immer das letzte Objekt ersetzt.
So ganz verstehen Tue ich dein Snippet aber nicht. Ich brauche doch kein append um eine neue Instanz einer Klasse zu erzeugen?

In meinem Snippet verwende ich immer den Letzten Namen der Liste, davor habe ich natürlich mit append immer einen neuen Namen zur Liste hinzugefügt.

Ich versuche das erstmal, so wie ich es im Moment glaube verstanden zu haben, in entzifferbarem Code aufzuschreiben und Poste es dann als Beispiel.

Gruß

NilsV
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Code: Alles auswählen

>>> class Lampe(object):
...     def __init__(self, watt, an=False):
...         self.watt = watt
...         self.an = an
... 
>>> lampen = []
>>> for i in range(5):
...     lampe = Lampe(i**2)
...     lampen.append(lampe)
... 
>>> lampen[0].watt
0
>>> lampen[1].watt
1
>>> lampen[2].watt
4
>>> lampen[3].watt
9
>>> 
Das Leben ist wie ein Tennisball.
NilsV
User
Beiträge: 30
Registriert: Dienstag 17. August 2010, 12:35

Hallo,

@EyDu
Die Anzahl der Lampen ist bei mir nicht festgelegt, ich möchte über meine Funktion neueLampe() jederzeit eine neue Lampe erzeugen können.

Hier ist mein Stand:

Code: Alles auswählen

# Klassen

class Lampen(object):
    def __init__(self, watt):   # Neue Lampe erzeugen, benötigt Namen und Watt
        self.watt = watt
        self.an = False
        print('Neue Lampe wurde Montiert.')
        


# Funktionen

def neueLampe(listeLampen, anzahlLampen):
    anzahlLampen = anzahlLampen + 1
    watt = int(input('Wieviel Watt hat die Glühbirne?:'))
    lampenName = 'lampe\b' + str(anzahlLampen)
    lampenName = Lampen(watt)
    print('Die neue Lampe heisst:', lampenName)
    return(listeLampen, anzahlLampen)


# Hauptprogramm

x = None
listeLampen = []
anzahlLampen = 0
while x != 'x':
    print('''

1       Neue Lampe erzeugen
x       Programm beenden
    ''')
    x = input('Bitte eine Aktion Wählen:')
    if x == '1':
        listeLampen, anzahlLampen = neueLampe(listeLampen, anzahlLampen)
    elif x == 'x':
        print('Programm beendet')
Die Zeile

Code: Alles auswählen

    lampenName = Lampen(watt)
in der Funktion neueLampe() scheint tatsächlich immer die selbe Instanz von Lampen zu überschreiben. Das Beispiel von cofi kann ich hier auch nicht anwenden (Für Strings gibt es kein append).

Würde ich die Klasse manuell in der IDLE füllen, könnte ich das einfach mit:

Code: Alles auswählen

>>>lampe1 = Lampen(60)
lampe2 = Lampen(40)
Warum funktioniert das nicht wenn ich den Namen der zu erzeugenden Instanz als String in lampenName habe?

Gruß

NilsV
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

So sollte es sein:

Code: Alles auswählen

def neueLampe(listeLampen):
    watt = int(input('Wieviel Watt hat die Glühbirne?:'))
    listeLampen.append(Lampe(watt))
    return listeLampen
Danach kannst du dann sowas machen:

Code: Alles auswählen

for lampe in listeLampen:
    print lampe.watt
Wenn du darauf bestehst, den Lampen Namen zu geben (wozu?), dann waere ein weiteres Objektattribut dafuer angebracht. Ausserdem solltest du listeLampen in lampen umbenennen. Es ist nicht noetig, den Klassennamen mitzuschleppen.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Ein wenig solltest du von dem Beispiel schon abstrahieren können:

Code: Alles auswählen

>>> class Lampe(object):
...     def __init__(self, watt):
...         self.watt = watt
...     def __repr__(self):
...         return "Lampe(%s)" % self.watt
... 
>>> lampen = []
>>> while True:
...     watt = raw_input("Watt?")
...     if not watt:
...         break
...     lampen.append(Lampe(float(watt)))
... 
Watt?23
Watt?42
Watt?
>>> print lampen
[Lampe(23.0), Lampe(42.0)]
In deiner Funktion wird übrigens nicht immer die selbe Lampe überschrieben, du erzeugst bei jedem Aufruf eine neue, verwendest sie dann aber nicht weiter.

Das Strings keine append Methode haben sollte doch klar sein. Du kannst nicht einfach etwas an irgendetwas anderes anhängen. Woher soll der Interpreter wissen was du meinst?
NilsV hat geschrieben:Warum funktioniert das nicht wenn ich den Namen der zu erzeugenden Instanz als String in lampenName habe?
Das funktioniert nicht, weil du einen neuen Wert an lampenName bindest. Jedes andere Verhalten würde zu vollkommenem Unfug führen ;-)

Um es noch einmal deutlich zu sagen: Dein Ansatz ist vollkommen falsch. Wenn du Namen generierst, dann ist das ein Fehler. Entweder möchtest du dann Listen/Tupel benutzen oder ein Dictionary.

Sebastian
Das Leben ist wie ein Tennisball.
Antworten