Zufalls-Koordinaten objektorientiert 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.
vogti
User
Beiträge: 31
Registriert: Mittwoch 21. Januar 2009, 21:53
Kontaktdaten:

Sonntag 13. September 2009, 15:13

Hallo,
ich habe beschlossen, mich ein wenig an die Objektorientierte Programmierung ran zu trauen. Mein erstes Ziel: eine Liste, welche aus 10 Tupeln besteht. Diese Tupel wiederum enthalten 2 Zahlen (sollen Koordinaten sein...).

Jetzt bin ich auf ein "Phänomen" gestoßen, welches ich mir nicht so recht erklären kann. Hier mein Code:

Code: Alles auswählen

#!/usr/bin/python
import random

class Zufall:
    box = []
    def __init__(self):
        self.a = (random.randint(0, 99), random.randint(0, 99))
        Zufall.box.append(self.a)
    
    def Ausgabe(self):
        print Zufall.box

for i in range(0, 10):
    print Zufall().box
Die Ausgabe davon (so wie es sein soll...):
>>> [(8, 11)]
[(8, 11), (96, 66)]
[(8, 11), (96, 66), (17, 22)]
[(8, 11), (96, 66), (17, 22), (22, 79)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84), (48, 98)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84), (48, 98), (38, 13)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84), (48, 98), (38, 13), (72, 79)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84), (48, 98), (38, 13), (72, 79), (57, 81)]
[(8, 11), (96, 66), (17, 22), (22, 79), (10, 84), (48, 98), (38, 13), (72, 79), (57, 81), (72, 64)]
Wenn ich jetzt aber Zufall().box in eine Variable test verpacke und diese innerhalb der for i in range(0,10) Schleife ausgebe, bekomme ich folgende Ausgabe:
>>> [(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
[(48, 30)]
Ich jemand dieses Verhalten erklären? Verstehe nicht so richtig, warum das passiert...


Gruß,
vogti
Zuletzt geändert von vogti am Sonntag 13. September 2009, 15:32, insgesamt 1-mal geändert.
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

Sonntag 13. September 2009, 15:26

Deine Methode 'Ausgabe' liefert keinen Wert zurück der "geprintet" werden kann. ersetzte mal das print durch ein return in deiner Methode Ausgabe.
BlackJack

Sonntag 13. September 2009, 15:26

@vogti: Ohne das Du den Code zeigst, der "in `test` verpacken" repräsentiert kann man da nur raten.

Wobei das Beispiel da recht wenig mit OOP zu tun hat. Und die sind auch die ganzen `None`-Ausgaben bei Deiner ersten Ausgabe aufgefallen? Warum machst Du das?
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Sonntag 13. September 2009, 15:35

So funktionierts:

Code: Alles auswählen

import random

class Zufall(object):
    box = []
    def __init__(self):
        self.a = (random.randint(0, 99), random.randint(0, 99))
        Zufall.box.append(self.a)
   
    def Ausgabe(self):
        return Zufall.box

for i in range(0, 10):
    zufall_ = Zufall()
    print zufall_.Ausgabe()
vogti
User
Beiträge: 31
Registriert: Mittwoch 21. Januar 2009, 21:53
Kontaktdaten:

Sonntag 13. September 2009, 15:37

Habe es eben nochmal angepasst. Ich versuche die Variable Zufall().box direkt auszugeben. So kommen keine "None" mehr - sondern immer nur ein und die Selbe Koordinate.

Hier der "vollständige" code mit der "test"-Variable:

Code: Alles auswählen

#!/usr/bin/python
import random

class Zufall:
    box = []
    def __init__(self):
        self.a = (random.randint(0, 99), random.randint(0, 99))
        Zufall.box.append(self.a)
    
    def Ausgabe(self):
        return Zufall.box

test = Zufall().box

for i in range(0, 10):
    print test
Ausgabe ist dabei immer 10x die gleiche Variable...

Was ich eigentlich machen möchte würde ich "nicht OOP" so lösen:

Code: Alles auswählen

#!/usr/bin/python
import random
box =  []

for i in range(0, 10):
    a = (random.randint(0, 10), random.randint(10, 25))
    box.append(a)
    print box

print box[4][1] #(möchte im Nachhinein per Indizes auf bestimmte Variablen zurückgreifen können)
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Sonntag 13. September 2009, 15:43

du bekommst 10 mal die gleiche Variable, weil du eine __init__ Funktion hast, diese wird nur einmal ausgeführt!

Code: Alles auswählen

box = []
def Zufall():

    a = (random.randint(0, 99), random.randint(0, 99))
    box.append(a)
   
    return box

for i in range(0, 10):
    print Zufall()
//Edit:

Zitat aus A Byte of Python (deutsch):
Die Methode __init__ wird aufgerufen, sobald ein Objekt einer Klasse instanziiert wird. Die
Methode kann dafür benutzt werden, ihr Objekt auf irgendeine Weise zu initialisieren. Beachten Sie
die doppelten Unterstriche sowohl am Anfang als auch am Ende des Namens.
the more they change the more they stay the same
vogti
User
Beiträge: 31
Registriert: Mittwoch 21. Januar 2009, 21:53
Kontaktdaten:

Sonntag 13. September 2009, 15:44

microkernel hat geschrieben:So funktionierts:

Code: Alles auswählen

import random

class Zufall(object):
    box = []
    def __init__(self):
        self.a = (random.randint(0, 99), random.randint(0, 99))
        Zufall.box.append(self.a)
   
    def Ausgabe(self):
        return Zufall.box

for i in range(0, 10):
    zufall_ = Zufall()
    print zufall_.Ausgabe()
Tatsächlich... So funktionierts. 2 Fragen dazu:
Zeile 4: Warum gibst du "Zufall(object)" an? Was bringt dieses "(object)"?
Zeile 14: Warum muss ich die Variable innerhalb der Schleife immer wieder neu deklarieren? Warum reicht es nicht "zufall_" vor der Schleife einmal zu belegen?
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Sonntag 13. September 2009, 15:46

Wie es aussieht, versuchst du zwanghaft irgend eine Funktion in OOP zu zwingen. OOP allerdings kein Selbstzweck. Und mit einem sinnfreien Beispiel wirst du es sicher nicht verstehen. Mach lieber etwas vernünftiges wie ein Adressbuch. Das lässt sich relativ direkt objektorientiert umsetzen, ist nicht zu schwer und du wirst hier im Forum einige Beispiele finden.
Das Leben ist wie ein Tennisball.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Sonntag 13. September 2009, 15:46

du musst sie neu deklarieren wegen der __init__ Methode

//Edit: hab da noch was gefunden: http://ubuntuforums.org/archive/index.php/t-540438.html
the more they change the more they stay the same
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Sonntag 13. September 2009, 17:47

Vogti, wenn du objektorientierst vorgehen willst, fängt das in der Problemanalyse an. Welches Problem willst du lösen? Wenn du das beschreiben kannst, kann du Objekte, ihr Verhalten und ihre Beziehungen zueinander identifizieren. Dann kannst du dir überlegen (wir kommen jetzt von der Analyse- in die Design-Phase), wie du deine Objekte realisierst, z.B. bietet sich in Python an, dazu Exemplare von Klassen zu benutzen. Und Methoden für das Verhalten. Und dann kannst du das implementieren. Das ist OOA/OOD/OOP.

Beispiel: Du willst einen Container haben, das 10 zufällige Koordinaten aufbewahrt. Das erste offensichtliche Objekt ist eine Koordinate. Sie habe zwei Attribute x und y. Diese sollen zufällig zwischen 0 und 99 liegen. Hier ist eine Design-Entscheidung zu treffen: Soll eine Koordinate selbst sich zufällig initialisieren können oder gibt es vielleicht ein weiteres Objekt, einen Würfel, der eine Zahl liefert, wenn man ihn wirft? Entscheiden wir uns für Variante zwei. Das dritte Objekt, was ich identifiziere, ist der Container (der gerne einen besseren Namen haben könnte denn irgendeinen Sinn muss der ja haben), der die Koordinaten enthalten soll. Auch hier wieder die Frage: Wer füllt ihn? Sagen wir hier der Einfachheit halber, er macht es selbst. Und er soll auch den Würfel kennen. Diesen "reinzureichen" entspricht dem "dependency injection"-Pattern, das sich bewährt hat, wenn man einfachen, testbaren Code schreiben will.

Also:

Code: Alles auswählen

class Dice(object):
    def __init__(self, sides):
        self.sides = sides
    
    def roll(self):
        return random.randint(0, self.sides)

class Coordinate(object):
    def __init__(self, x, y):
        self.x, self.y = x, y
    
    def __repr__(self):
        return "%d/%d" % (self.x, self.y)

class Container(object):
    def __init__(self, n, dice):
        self.coordinates = [self.random_coordinate(dice) for i in range(n)]
    
    def random_coordinate(self, dice):
        return Coordinate(dice.roll(), dice.roll())

print Container(10, Dice(100)).coordinates
Stefan
Zuletzt geändert von sma am Sonntag 13. September 2009, 18:12, insgesamt 2-mal geändert.
BlackJack

Sonntag 13. September 2009, 17:58

@sma: Kann es sein, das bei den Würfeln jeweils ein 'c' fehlt!?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Sonntag 13. September 2009, 18:11

BlackJack hat geschrieben:@sma: Kann es sein, das bei den Würfeln jeweils ein 'c' fehlt!?
Ja, konnte sein. Ich war dem Irrglaube unterlegen, die Einzahl von "dice" wäre "die" und nicht auch "dice". Ich <-- doof.

Stefan
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 14. September 2009, 12:09

sma hat geschrieben:Ja, konnte sein. Ich war dem Irrglaube unterlegen, die Einzahl von "dice" wäre "die" und nicht auch "dice".
Da musste ich grade überlegen, denn ich hätte den selben Irrglauben. Stellt sich aber dank Wikipedia heraus, dass beides irgendwie richtig ist: "die" ist en_US und "dice" ist en_UK.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mittwoch 16. September 2009, 10:19

Prima, doch kein Irrglaube. Als ich allerdings schnell bei dict.leo.org nachschaute, kannte der Dienst ein "die" als Würfel. Aber jetzt ändere ich das nicht wieder in "American English" zurück. Hier -> http://www.peginc.com/Downloads/SWEX/TD06.pdf steht dann z.B. auch überall "die" statt "dice", wenn's um die Einzahl geht.

Stefan
Benutzeravatar
snafu
User
Beiträge: 5627
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 16. September 2009, 10:37

Ich dachte immer, "dice" sei die Einzahl und "dices" die Mehrzahl. Jedenfalls gibt es hier eine Band, die auf "and the dices" endet.
shcol (Repo | Doc | PyPi)
Antworten