Mehrere Instanzen erzeugen...

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
Saugwels98
User
Beiträge: 9
Registriert: Samstag 2. November 2013, 16:24
Wohnort: Erlangen

Hey Leute,
ich arbeite gerade an einen Bioinformatik-Script und benötige kurz eure Hilfe.
Momentan erzeuge ich eine Instanz "Bakterie".

Code: Alles auswählen

bakterie = []
#Gameloop
while True:
    screen.fill((0,30,50))
    bakterie.zeichne(f)
    bakterie.bewegung()
Nun ist es aber schwer vorstellbar, das es nur eine Bakterie gibt. Um also mehr bakterien zu erzeugen, wäre der erste Ansatz so:

Code: Alles auswählen

bakterie = lebewesen()
#Gameloop
while True:
    screen.fill((0,30,50))
    bakterie.zeichne(f)
    bakterie.bewegung()
    bakterie2.zeichne(f)
    bakterie2.bewegung()
Aber gib es nicht eine Möglichkeit, wie bei C#?:

Code: Alles auswählen

bakterie [] = {lebewesen(),lebewesen(),...}
Also mehere Instanzen in einen Array zu speichern und dann alle gleichzeitig aufrufen zu können?

Meine Idee wäre folgene, aber ich bekomme eine Fehlermeldung:

Code: Alles auswählen

bakterie1 = lebewesen()
bakterie2 = lebewesen()

bakterie = [bakterie1, bakterie2]
Hat jemand einen Lösungsvorschlag?

Vielen Dank im Vorraus,
Paul
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

1. Paste bitte lauffähigen Minimalcode, den wir testen können.

2. du kannst eine list comprehension benutzen: ``bakterien = [Bakterie() for _ in xrange(10)]`` erzeugt 10 Instanzen von Bakterie.

Und warum dein letzter Versuch nicht funktioniert, kann ich dir ohne weiteren Code und die komplette Fehlermeldung nicht sagen.

Edit: Außerdem ist es möglich, Listen von Instanzen einfach so zu definieren: ``bakterien = [Lebewesen(), Lebewesen(), Lebewesen()]``
Zuletzt geändert von derdon am Sonntag 3. November 2013, 22:15, insgesamt 1-mal geändert.
BlackJack

@Saugwels98: „Ich bekomme eine Fehlermeldung” ist eine tolle Aussage. Aber total nutzlos ohne zu wissen *was* für eine.

Im ersten Quelltext müsstest Du eine Fehlermeldung bekommen weil Du `bakterie` an eine Liste bindest und darauf dann die Methoden `zeichne()` und `bewege()` aufrufst — die Listen allerdings nicht besitzen.

Beim zweiten Quelltext ist `bakterie2` nirgends definiert.

Kann man bei C# tatsächlich eine Methode auf dem Array aufrufen die dann automagisch an alle Exemplare weitergereicht wird!?

Das was Du im dritten Quelltext machst sollte keine Fehlermeldung geben, jedenfalls nicht im gezeigten Ausschnitt.

Das binden an die nummerierten Namen ist unnötig. Hast Du mal ein Python-Grundlagentutorial durchgearbeitet? Falls ja, verstehe ich nicht wie man in einem Tutorial so etwas wie ``xs = [42, 23, 4711]`` lesen kann und nicht darauf kommen kann, dass man anstelle der Zahlen natürlich auch jeden beliebigen anderen Wert oder Ausdruck der zu einem Wert ausgewertet werden kann, schreiben kann. Also zum Beispiel ``bakterien = [lebewesen(), lebewesen()]``. Falls `lebewesen` keine Funktion ist sondern eine Klasse, dann bitte mal den Style Guide for Python Code lesen.
Saugwels98
User
Beiträge: 9
Registriert: Samstag 2. November 2013, 16:24
Wohnort: Erlangen

Hey,

vielen Dank für die Antworten(: Mit Fehlermeldung meinte ich übrigends, dass meine Idee nicht funktionierte.
Saugwels98
User
Beiträge: 9
Registriert: Samstag 2. November 2013, 16:24
Wohnort: Erlangen

@BackJack

Bei "Lebewesen" handelt es sich um eine Klasse. Ja, ich habe die Python-grundlagen auf Codeacademy mir erarbeitet. Es tut mir leid, dass ich nicht wusste, dass man in einen Array auch Ausdrücke speichern kann. Im zweiten Quelltext hab ich bakterie2 nicht defieniert, um euch nur meine Idee anzudeuten. Von einen Style Guide wusste ich bisher garnichts. Vielen Dank für die gewonnenen Informationen.
BlackJack

@Saugwels98: Das Array heisst in diesem Fall Liste und man kann darin keine Ausdrücke speichern sondern Werte. Und die können natürlich durch beliebige Ausdrücke entstehen. Letztendlich ist eine einfache Zahl oder eine literale Zeichenkette doch auch ein Ausdruck. Genau wie die literale Liste selber, denn der Ausdruck ergibt ja auch einen Wert, der dann im Beispiel an einen Namen gebunden wird.
Saugwels98
User
Beiträge: 9
Registriert: Samstag 2. November 2013, 16:24
Wohnort: Erlangen

@Black Jack

Vielleicht sollte ich meine Frage anders stellen.

Momentan wird 1 Bakterie erzeugt. Diese kann sich bewegen durch bewege()

Falls ich nun 3 Bakterien haben möchte, die sich bewegen, müsste ich das hier schreiben:

Code: Alles auswählen

bakterie = lebewesen()
bakterie2 = lebewesen()
bakterie3 = lebewesen()


#Gameloop

while True:

    screen.fill((0,30,50))


    bakterie.zeichne(f)
    bakterie.bewegung()

    bakterie2.zeichne(f)
    bakterie2.bewegung()

    bakterie3.zeichne(f)
    bakterie3.bewegung()
Nun frag ich mich, ob es die Möglichkeit gibt, diese 3 "bakterien-Instanzen" in eine Liste zu speichern und sie dann zum Beispiel durch:

Code: Alles auswählen

 BAKTERIENLISTE.zeichne(f)
aufzurufen.

Hier ist noch einmal die Klasse Lebewesen:

Code: Alles auswählen

class lebewesen(object):

    def __init__(self):
        self.groesse  = 4
        self.x   = random.randint(200, 300)
        self.y    = random.randint(200, 300)
    def bewegung(self):
        be = [-1,0,1]
        plusx = random.choice(be)
        plusy = random.choice(be)
        self.x += plusx
        self.y += plusy

    def zeichne(self,f):
        pygame.draw.rect(screen,f,((self.x,self.y),(2,2)))
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Saugwels98 hat geschrieben:Nun frag ich mich, ob es die Möglichkeit gibt, diese 3 "bakterien-Instanzen" in eine Liste zu speichern und sie dann zum Beispiel durch:

Code: Alles auswählen

 BAKTERIENLISTE.zeichne(f)
aufzurufen.
Nein, das geht so nicht.

Es geht aber trotzdem total simpel. Gesetzt den Fall, die Bakterien befänden sich in einer Liste namens bakterien, dann sähe das so aus:

Code: Alles auswählen

for bakterie in bakterien:
    bakterie.zeichne(f)
Wenn du sehr viel Wert darauf legst, dass der Container eine eigene zeichne-Methode hat, dann musst du den selber schreiben.

Ich möchte dir auch noch das offizielle Tutorial (bitte passende Version auswählen) und den Style Guide for Python Code ans Herz legen.
Zuletzt geändert von /me am Montag 4. November 2013, 18:02, insgesamt 1-mal geändert.
BlackJack

@Saugwels98: Nein, aber man würde die normalerweise in eine Liste stecken und dann in einer Schleife alle durchgehen und die entsprechenden Methoden aufrufen, statt alle einzeln hinzuschreiben und an durchnummerierte Namen zu binden.

Man könnte auch eine Klasse schreiben, welche die Lebewesen zusammenfasst, also intern zum Beispiel in einer Liste hält und dort dann die Methoden für bewegen und zeichnen implementieren. Die müssten dann natürlich auch wieder über die einzelnen Elemente der Liste iterieren und ihrerseits die passenden Methoden dort aufrufen.

Bei so einer Containerklassen bekommt man bei deutschen Namen dann ein Problem was man bei englischen in aller Regel nicht hat: Plural hat genau die gleiche Schreibweise wie Singular. Für eine Containterklasse würde man nämlich normalerweise einfach den Plural von dem was sie enthält und verwaltet verwenden. Das geht im Englischen fast immer, im Deutschen leider nicht. Zum Beispiel nicht bei Lebewesen.

`lebewesen.groesse` wird nirgends verwendet. Statt `x` und `y` würde ich hier eher ein `pygame.Rect`-Objekt empfehlen. Das hat zum Beispiel auch Methoden um es zu verschieben.

`screen` in der `zeichne()`-Methode kommt auf magische Weise aus dem Nichts. Das sollte entweder an die `__init__()` oder besser an `zeichne()` direkt als Argument übergeben werden.

Den Bereich aus dem die Startwerte genommen werden, würde ich konfigurierbar machen. Praktisch wird der ja wahrscheinlich von der Grösse der Anzeigefläche abhängen, also sollte man ihn vielleicht auch relativ dazu machen.

Man könnte sich auch überlegen die Klassen aus `pygame.sprite` als Grundlage für die Lebewesen und die Containerklasse zu verwenden.
Saugwels98
User
Beiträge: 9
Registriert: Samstag 2. November 2013, 16:24
Wohnort: Erlangen

Vielen vielen Dank an euch alle(:
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Code: Alles auswählen

>>> class Foo:
...   def bar(self):
...     return 1
... 
>>> foos = [Foo() for _ in range(5)]
>>> from operator import methodcaller
>>> map(methodcaller('bar'), foos)
[1, 1, 1, 1, 1]
Intern macht das aber auch nichts anderes, als über alle Objekte zu gehen und die Methode aufzurufen.
BlackJack

@jerch: Wobei ich das nur so machen würde wenn man wirklich eine Liste mit Rückgabewerten haben möchte. Bei `lebewesen` ruft man die Methode ja aber rein wegen des Effekts auf und nicht weil man eine Liste mit Werten haben möchte.
Antworten