ubuntuusers.de

Python: Eingabeparameter bei constructor

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

Sauer2

Anmeldungsdatum:
5. Mai 2008

Beiträge: Zähle...

Ich habe ein Problem:

class spycam:
	posx = 0
	posy = 0
	width = 12
	height = 12
	broken = 1
	def _init_(self,inputx,inputy):
		self.posx = inputx
		self.posy = inputy
		camlist.append(self)

Weiter unten in def_main wird eine Instanz davon via camA = spycam(123,234) erstellt, allerdings meckert der Interpreter trotzdem, dass der constructor eigentlich keine Argumente entgegennimmt.

Außerdem habe ich eine Frage: Man sieht, dass ich versuche, der Liste Objekte bzw. deren Zeiger hinzuzufügen versuche. (ähnlich wie bei TList von Freepascal)

Funktioniert das bei Python, oder brauche ich dafür eine spezielle, andere Datenstruktur? Kann man dann auch mehrere Objektinstanzen 'cama' erschaffen, bei denen dann jeweils der Zeiger der vorherigen überschrieben wird, man aber die alten Werte über die Liste abrufen und verändern kann?

mfg

Sauer2

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4686

Wohnort: Berlin

Du solltest vielleicht erst einmal einen Konstruktor bzw. eine __init__()-Methode für die Klasse schreiben. Such Dir ein funktionierendes Beispiel und zähle da mal die Unterstriche vor und nach dem init. 😉

Vielleicht solltest Du auch das Tutorial aus der Python-Dokumentation durcharbeiten. Danach kannst Du bestimmt verraten, ob es Absicht ist, dass Du da so viele Klassenattribute definiert hast, oder ob die nur an der Stelle stehen, weil Du das von anderen Programmiersprachen so gewohnt bist.

Deine weiteren Fragen finde ich etwas verwirrend. Es gibt in Python keine Zeiger als Datentyp. Nur Objekte. Und es gibt Namen, die auf Objekte verweisen. Genau wie Einträge in Datenstrukturen auf Objekte verweisen.

Der Zugriff auf camlist in der __init__() sieht ungesund aus. Das würde ich so auf den ersten Blick in keiner Programmiersprache für einen guten Entwurf halten.

Last but not least gibt's bei vielen Programmiersprachen verbreitete Konventionen. Bei Python wären das zum Beispiel MixedCase für Klassennamen, kleine_buchstaben_und_unterstriche für fast alles andere und Einrückung mit vier Leerzeichen pro Ebene. Falls broken einen Wahrheitswert darstellen soll, wären True und False eindeutiger als 1 und 0.

Sauer2

(Themenstarter)

Anmeldungsdatum:
5. Mai 2008

Beiträge: 496

Zu 1. Besten Dank!

Zu 5. Hab ich geändert, danke!

Zu 2. Ich bin das tatsächlich so gewohnt. Sollte ich das lieber als eine Datenstruktur (Tupel oder wie das heißt) 'data' zusammenfassen?

Zu 3. und 4. Das funktioniert dann also nicht. Ich will die Instanz halt direkt in eine Liste kopieren, wenn sie erstellt wird, denn ich will ja nicht für jede Instanz einen eigenen Namen erstellen. Soll ich das dann so machen, dass sich nur die Werte in der Liste befinden?

Sauer2

(Themenstarter)

Anmeldungsdatum:
5. Mai 2008

Beiträge: 496

Update zu 2. : Ich hab das jetzt als data = (123,345,True) angeordnet, falls Du meintest.

YEPHENAS

Anmeldungsdatum:
8. Juni 2009

Beiträge: 352

Sauer2 schrieb:

Zu 2. Ich bin das tatsächlich so gewohnt. Sollte ich das lieber als eine Datenstruktur (Tupel oder wie das heißt) 'data' zusammenfassen?

Nein, er meinte, dass du da Klassenvariablen statt Instanzvariablen setzt. Instanzvariablen musst du auf self setzen, am besten in der __init__-Methode, oder wo sie sonst das erste Mal benötigt werden.

Edit - Erklärung: http://abop-german.berlios.de/read/class-and-object-vars.html (Hier werden sie Objektvariablen genannt)

Holger63

Avatar von Holger63

Anmeldungsdatum:
8. Juni 2006

Beiträge: 695

Wohnort: Wesel, Nordrhein-Westfalen

Sauer2 schrieb:

Zu 2. Ich bin das tatsächlich so gewohnt. Sollte ich das lieber als eine Datenstruktur (Tupel oder wie das heißt) 'data' zusammenfassen?

Marc will damit sagen, dass die Klasse wahrscheinlich nicht dem entspricht, was du haben wolltest. Du hast eine Klasse, die (unabhängig von einer Instanz) über die Attribute posx, posy, width und height verfügt. Wenn du jetzt z.B. 2 Instanzen anlegst und den Wert für width änderst, dann haben beide Instanzen plötzlich geänderte width-Einstellungen:

1
2
3
4
5
6
7
cam1 = spycam(1,2)
cam2 = spycam(3,4)
print cam1.width, cam2.width
12 12
spycam.width = 100
print cam1.width, cam2.width
100 100

In Python werden die Attribute normalerweise im Konstruktor gesetzt:

1
2
3
4
5
6
class SpyCam(object):
    def __init__(self, posx, posy):
        self.posx = posx
        self.posy = posy
        self.width = 12
        self.height = 12

Zu 3. und 4. Das funktioniert dann also nicht.

Doch, das funktioniert einwandfrei. Man kann Objekte in Listen speichern.

Ich will die Instanz halt direkt in eine Liste kopieren, wenn sie erstellt wird

Dann solltest du sie dort hinzufügen, wo du auch die Liste definiert hast. Eine Instanz kann z.B. so in eine Liste eingetragen werden:

1
2
camlist = []
camlist.append( spycam(123, 234) )

Das Hinzufügen innerhalb des Konstruktors schränkt die Wiederverwendbarkeit der Klasse extrem ein. Was ist, wenn die Instanz in einer anderen Liste verwaltet werden soll oder in keiner Liste erscheinen soll? Außerdem muss im aktuellen Namensraum immer eine Liste namens camlist vorhanden sein.
Wer entfernt eigentlich den Eintrag später aus der Liste? Die Instanz entscheidet darüber, wann in der Liste ein Eintrag hinzugefügt wird, aber an einem anderen Ort wird entschieden, wann der Eintrag wieder entfernt wird - das ist sehr verwirrend und kein guter Programmierstil. Derjenige (Funktion oder Klasse), der die Liste verwaltet, sollte in der Regel auch selbst die Einträge hinzufügen und wieder entfernen.

Gruß, Holger

YEPHENAS

Anmeldungsdatum:
8. Juni 2009

Beiträge: 352

Sauer2 schrieb:

Außerdem habe ich eine Frage: Man sieht, dass ich versuche, der Liste Objekte bzw. deren Zeiger hinzuzufügen versuche. (ähnlich wie bei TList von Freepascal)

Ich weiß nicht, ob du das meinst, aber Variablen zu Objekten sind Referenzen, so wie in den meisten anderen OO-Programmiersprachen auch. Man nennt es halt nicht Zeiger, weil man damit keine Pointerarithmetik und Co. betreiben kann.

Sauer2

(Themenstarter)

Anmeldungsdatum:
5. Mai 2008

Beiträge: 496

@ Holger63: Ich sehe, wir reden prima aneinander vorbei. Ich will eigentlich nur die Instanzen in die Liste tun. Wegen der Sache mit dem Hinzufügen: Recht hast Du, also nichts wie geändert. Und Danke für die anschaulichen Beispiele.

Kann ich also in einer For-Schleife sowas machen

positions = ((23,234),(67,232),...,(xn,yn))
for pos in positions:
    cam_instanz = SpyCam(pos)
    cam_list.append(cam_instanz)

und die ganzen in der Liste gespeicherten Instanzen dann mit einer Schleife dann auch wieder abrufen?

@ Yepehnas: Keine Ahnung, hat mein ehem. Infolehrer behauptet, darf also ruhig als kontrovers betrachtet werden. 🤣

Holger63

Avatar von Holger63

Anmeldungsdatum:
8. Juni 2006

Beiträge: 695

Wohnort: Wesel, Nordrhein-Westfalen

Sauer2 schrieb:

@ Holger63: Ich sehe, wir reden prima aneinander vorbei.

Nein, das glaube ich nicht 😀

Kann ich also in einer For-Schleife sowas machen [...]

Du erzeugst eine Instanz und weist sie einer Variablen zu. Die Variable hängst du dann an die Liste. Das kannst du problemlos so machen. Ich habe mir in meinem Beispiel den Umweg über eine Variable erspart und die Instanz direkt zur Liste hinzugefügt. Ein SpyCam(pos) erzeugt ja eine Instanz. Ob diese Instanz jetzt erst einer Variablen und dann der Liste zugewiesen wird oder ob sie direkt in der append-Funktion übergeben wird ist vollkommen gleichgültig.

und die ganzen in der Liste gespeicherten Instanzen dann mit einer Schleife dann auch wieder abrufen?

Ja, du kannst z.B. mit

1
2
for cam in cam_list:
    print cam.<irgendwas>

oder

1
2
for index in xrange(len(cam_list)):
    print cam_list[index].<irgendwas>

direkt auf die einzelnen Instanzen zugreifen.

Gruß, Holger

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

Sauer2 schrieb:

Kann ich also in einer For-Schleife sowas machen

positions = ((23,234),(67,232),...,(xn,yn))
for pos in positions:
    cam_instanz = SpyCam(pos)
    cam_list.append(cam_instanz)

und die ganzen in der Liste gespeicherten Instanzen dann mit einer Schleife dann auch wieder abrufen?

Ja.

Sauer2

(Themenstarter)

Anmeldungsdatum:
5. Mai 2008

Beiträge: 496

Klasse, Danke!

EDIT: @diesch: Leider zu spät aber trotzdem Danke für die Mühe! 😉

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

YEPEHNAS schrieb:

Sauer2 schrieb:

Außerdem habe ich eine Frage: Man sieht, dass ich versuche, der Liste Objekte bzw. deren Zeiger hinzuzufügen versuche. (ähnlich wie bei TList von Freepascal)

Ich weiß nicht, ob du das meinst, aber Variablen zu Objekten sind Referenzen, so wie in den meisten anderen OO-Programmiersprachen auch. Man nennt es halt nicht Zeiger, weil man damit keine Pointerarithmetik und Co. betreiben kann.

In Python sind Variablen technisch gesehen Keys für einen dict, keine Zeiger.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4686

Wohnort: Berlin

Von dem Beispiel mit dem xrange(len(cams)) würde ich abraten. Wenn man keinen Index braucht, ist das direkte iterieren über die Liste einfacher und für den anderen Fall gibt es enumerate(). Man könnte das Erzeugen der Liste auch mit map() oder einer "list comprehension" machen:

1
2
3
4
positions = ((23, 234), (67, 232))
cameras = map(SpyCam, positions)
# oder
cameras = [SpyCam(p) for p in positions]

Sauer2

(Themenstarter)

Anmeldungsdatum:
5. Mai 2008

Beiträge: 496

Ja, danke, aber ich glaube, einen Index brauche ich eventuell schon.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4686

Wohnort: Berlin

@Sauer2: Wozu? Und wenn dann bitte mit enumerate().

Antworten |