Frage zu Listen und Objekten

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

legargeomatrix hat geschrieben: Ja, dass es auch ohne geht ist mir klar, doch das Projekt wird auch dazu dienen, OOP zu unterrichten, darum die strikte OOP-Schreibweise.
Was haben denn getter und setter mit OOP zu tun? *wunder*

Wie gesagt, bei Java, C# (afaik) und C++ ist das sicher ok. Aber bei Sprachen ohne Zugriffsschutzmechanismen benötigen so etwas nun einmal nicht! Wieso also etwas falsches* lehren?

(* im Sinne von Sprach-Idiomen!)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

legargeomatrix hat geschrieben:Ja, dass es auch ohne geht ist mir klar, doch das Projekt wird auch dazu dienen, OOP zu unterrichten, darum die strikte OOP-Schreibweise.

Nur weil man in Java für jeden Mist getter und setter braucht, ist das doch noch nicht DIE OOP-Schreibweise. Python zeigt doch gerade, dass es auch einfacher und eleganter geht. Oder willst du mit diesem Python-Programm eine Einführung in OOP für Java geben ...
BlackJack

@legargeomatrix: Wenn man mit 10⁷ Objekten arbeitet sollte man halt auch damit leben dass das etwas dauert.

Die Getter und Setter haben nichts mit OOP zu tun und wenn Du für ein Attribut *beides* hast, dann ist das totaler Unsinn weil es vom Effekt das selbe ist wie gleich auf das Attribut direkt zuzugreifen.

In Java macht man diesen Blödsinn statt einfach das Feld ``public`` zu deklarieren, weil man sich sonst später nicht umentscheiden kann einen "berechneten" Zugriff durchzuführen, ohne das sich Quelltext bei den ganzen vorhandenen Zugriffen auch ändern muss. Dieses Problem gibt es Python aber nicht -- dafür ist `property()` da. In Python machst Du Dir also nur völlig unnötige Schreibarbeit die den Quelltext ohne Mehrwert aufbläht und die Laufzeit verlangsamt.

Und wenn Du schon so auf OOP Wert legst, solltest Du Dir die erste Zeile in `delete()` vielleicht noch einmal überlegen ob das wirklich so toll ist die Polymorphie an der Stelle auszuhebeln in dem `Knoten.get_vater()` verwendet wird, egal von welchem Typ `self` wirklich ist. Du setzt da auch `self.kinder` auf eine leere Liste -- allerdings haben die Kinder ja wahrscheinlich einen Verweis auf *diesen* Knoten und der bleibt -- ist das okay?

@Hyperion: Properties gibt's in C# auch.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

numerix hat geschrieben:@Darii: Dein gezeigter Code ist gar nicht lauffähig ...
Meine Güte, dann Pack halt noch nen xrange ums len.
Aber im Ernst: "massiv schneller" wird das dadurch nicht.
Der Flaschenhals ist hier auch nicht das Befüllen oder Anhängen an die Liste, sondern die vielen Instanzbildungen.
Interessant woran das vorhin lag, bei mir kamen vorhin 10 Sek raus, jetzt ist es gleich, muss das morgen nochmal prüfen. Ehrlich gesagt erstaunt es mich, dass append so schnell ist.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Hier noch mal 'n Benchmark zu dem Thema:

Code: Alles auswählen

import numpy

t = clock()
f1 = [None] * 1000000
for i in xrange(1000000):
    f1[i] = i
print clock() - t

t = clock()
f2 = []
for i in xrange(1000000):
    f2.append(i)
print clock() - t

t = clock()
f3 = numpy.empty(1000000)
for i in xrange(1000000):
    f3[i] = i
print clock() - t
Nimmt sich alles nich viel...

Code: Alles auswählen

0.389669636783
0.550597073092
0.492012252954
legargeomatrix
User
Beiträge: 9
Registriert: Dienstag 27. April 2010, 16:11

BlackJack hat geschrieben:@legargeomatrix: Wenn man mit 10⁷ Objekten arbeitet sollte man halt auch damit leben dass das etwas dauert.

Die Getter und Setter haben nichts mit OOP zu tun und wenn Du für ein Attribut *beides* hast, dann ist das totaler Unsinn weil es vom Effekt das selbe ist wie gleich auf das Attribut direkt zuzugreifen.

In Java macht man diesen Blödsinn statt einfach das Feld ``public`` zu deklarieren, weil man sich sonst später nicht umentscheiden kann einen "berechneten" Zugriff durchzuführen, ohne das sich Quelltext bei den ganzen vorhandenen Zugriffen auch ändern muss. Dieses Problem gibt es Python aber nicht -- dafür ist `property()` da. In Python machst Du Dir also nur völlig unnötige Schreibarbeit die den Quelltext ohne Mehrwert aufbläht und die Laufzeit verlangsamt.

Und wenn Du schon so auf OOP Wert legst, solltest Du Dir die erste Zeile in `delete()` vielleicht noch einmal überlegen ob das wirklich so toll ist die Polymorphie an der Stelle auszuhebeln in dem `Knoten.get_vater()` verwendet wird, egal von welchem Typ `self` wirklich ist. Du setzt da auch `self.kinder` auf eine leere Liste -- allerdings haben die Kinder ja wahrscheinlich einen Verweis auf *diesen* Knoten und der bleibt -- ist das okay?

@Hyperion: Properties gibt's in C# auch.
Besser?

Code: Alles auswählen

class Knoten(object):
    """Knoten-Klasse fuer die Knoten des Spielbaums"""

    def __init__(self, stellung, vater, tiefe):
        self.stellung = stellung
        #die Tiefe entspricht der Runde, in der der Knoten gespielt wurde
        self.tiefe = tiefe
        self.kinder = []
        self.vater = vater
        self.bewertung = None
        self.blatt = False

    #ersetzt del self, denn die pointers muessen entfernt werden
    def delete(self, spielbaum):
        for kind in self.kinder:
            kind.vater = None
        self.kinder = []
        self.vater.kinder.remove(self)
        spielbaum.remove(self)
        return spielbaum
Mein Hauptcode sieht damit übrigens auch besser aus :)
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

legargeomatrix hat geschrieben:Ja, dass es auch ohne geht ist mir klar, doch das Projekt wird auch dazu dienen, OOP zu unterrichten, darum die strikte OOP-Schreibweise.
Es ist die Frage was man unterrichten will.

Auch ohne Getter und Setter ist es objektorientiert und warum der zusätzliche Overhead zu besserem und effektiverem Code führen soll ist mir nicht wirklich klar. Wenn zusätzliche Funktion gefordert wird, dann ist mir das klar, aber selbst das lässt sich, wenn eine Änderung in diese Richtung erst nach einiger Zeit gewünscht wird, hervorragend über den @property-Decorator abhandeln.
BlackJack

@legargeomatrix: Ist `blatt` nicht irgendwo redundant? Das ist doch dann der Fall wenn `kinder` leer ist, oder? Also würde ich da entweder eine Testmethode für schreiben und `blatt` weglassen oder das Attribut entsprechend als `property()` definieren. Als Testmethode:

Code: Alles auswählen

    def ist_blatt(self):
        return bool(self.kinder)
Und wenn's "pythonisch" sein soll machen auf Knoten-Objekten IMHO `__len__()` für die Anzahl der Kinder und `__iter__()` zum Iterieren über die Kinder Sinn.

Code: Alles auswählen

    def __len__(self):
        return len(self.kinder)
    
    def __iter__(self):
        return iter(self.kinder)
Wenn es die beiden Methoden gibt, kann man mit Knoten-Exemplaren z.B. so umgehen:

Code: Alles auswählen

    for kind in knoten:
        print 'Knoten hat %d Kinder' % len(kind)
Antworten