Seite 2 von 2

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 11:55
von BlackJack
@schneitzmaster: Ein führender Unterstrich bei lokalen Namen wird von einigen Programmierern als Kennzeichnung von Namen die nicht verwendet werden benutzt. Warum hast Du den in `Feder.deltaX()` verwendet? Den Namen hätte ich wahrscheinlich sowieso weg gelassen.

Der „längliche Befehl” ist eigentlich normal. Normal wäre auch `erdbeschleunigung` statt `g`, `masse` statt `M`, und `kraft` statt `F` zu verwenden.

Je nachdem wie das konkrete Problem aussieht welches man lösen möchte könnte man `Feder.auto` auch allgemeiner benennen. `Feder.last` oder so.

Die 1 bei `feder1` sollte da auch weg. Wenn man anfängt Namen mit Nummern zu ergänzen, will man in 99% der Fälle eigentlich die Werte in eine Datenstruktur stecken. Zum Beispiel in eine Liste.

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 12:21
von mutetella
@schneitzmaster
Ich verstehe nicht wirklich, was Du mit 'eleganter' meinst. Deine Lösung macht doch das, was sie soll, oder was erwartest Du anderes?

Ich hab' Deinen Code insofern angepasst, dass ein Auto mehrere Federn besitzen kann um zu demonstrieren, dass sich eine Änderung auf die Masse auch auf eine erneute Berechnung von 'delta_X' auswirkt ohne dies explizit den Federn mitzuteilen:

Code: Alles auswählen

class Damper(object):
    def __init__(self, number, stiffness, car):
        self.number = number
        self.stiffness = stiffness
        self.car = car

    @property
    def delta_X(self):
        return self.car.force / self.stiffness

class Car(object):
    gravity = 9.81
    def __init__(self, mass, *dumpers):
        self.mass = mass
        self.dampers = [
            Damper(number, stiffness, self) for number, stiffness in dumpers]

    @property
    def force(self):
        return self.mass * self.gravity

    def get_dampers(self):
        return [(damper.number, damper.delta_X) for damper in self.dampers]

Code: Alles auswählen

>>> c = Car(2000.0, ('1', 100.0), ('2', 100.0), ('3', 200.0), ('4', 200.0))
>>> c.get_dampers()
[('1', 196.19999999999999), ('2', 196.19999999999999), ('3', 98.099999999999994), ('4', 98.099999999999994)]
>>> c.mass = 1000.0
>>> c.get_dampers()
[('1', 98.099999999999994), ('2', 98.099999999999994), ('3', 49.049999999999997), ('4', 49.049999999999997)]
mutetella

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 12:49
von mutetella
schneitzmaster hat geschrieben:Leider weiß ich nicht genau wie er das mit den Methoden zum setzen und ändern gemeint hat.
Damit meinte ich, dass Du Klassen über deren Methoden verbinden kannst. Letztlich ist das eine Detailfrage. Ich persönlich mag diese property-Geschichten nicht besonders. Wenn ich ein Attribut abfrage, möchte ich ein Attribut abfragen und nicht eine Methode dahinter aufrufen. Ok, oft drängt sich einem ein property förmlich auf (z. B. bei Koordinaten) und manchmal mag es auch Sinn machen... Ist halt auch geschmackssache.
Zudem gefällt es mir besser, wenn immer nur so viel an Information weitergegeben wird, wie auch wirklich notwendig ist. In Deinem Fall finde ich, dass eine Feder nicht alle Informationen des Autos benötigt. Eine Feder muss noch nicht einmal wissen, dass sie in ein Auto verbaut ist. Die gerade gezeigt Lösung könnte also auch so aussehen:

Code: Alles auswählen

class Damper(object):
    def __init__(self, number, stiffness, load):
        self.number = number
        self.stiffness = stiffness
        self.load = load

    @property
    def delta_X(self):
        return self.load() / self.stiffness

class Car(object):
    gravity = 9.81
    def __init__(self, mass, *dumpers):
        self.mass = mass
        self.dampers = [
            Damper(number, stiffness, self.force) for 
            number, stiffness in dumpers]

    def force(self):
        return self.mass * self.gravity

    def get_dampers(self):
        return [(damper.number, damper.delta_X) for damper in self.dampers]
Das macht, wie BlackJack schon erwähnt hat, die 'Damper'-Klasse auch unabhängiger.

mutetella

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 13:56
von schneitzmaster
@BlackJack: Ich habe den Unterstrich verwendet um klar zu machen, dass diese Variable nicht von Feder exportiert werden soll, sondern nur lokal in der Methode zugewiesen wird um die danach folgende Rechnung "Übersichtlicher zu machen". Im Python-Wiki habe ich diese Notation gefunden (http://de.wikibooks.org/wiki/Python_unt ... und_um_OOP --> "Privat - mehr oder weniger").
Bei meinem tatsächlichen Problem sind die Formeln sehr länglich und da wird es schnell unübersichtlich wenn jedesmal mit dem Punktoperatur darauf zugreift. Deswegen finde ich es an der stelle praktischer eine lokale Variable einzuführen.

@mutetella: Tatsächlich ist es so, dass ich ein differentialgeometrisches Problem programmiere, wo die Koordinaten des "Master"-Körpers in der Masterklasse berechnet werden und sich dann daraus die Koordinaten der "Slave"-Körper rechnerisch in der Slaveklasse bestimmen. Ich glaube dass da property, zu mindest für mich, der beste und einfachste weg ist.

Ich habe jetzt nur noch eine letzte Frage. Warum ist in deinem Code bei der Definition von delta_X load() eine Methode obwohl doch load in der Klasse Damper als Attribut initialisiert wird?

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 14:31
von mutetella
schneitzmaster hat geschrieben:... obwohl doch load in der Klasse Damper als Attribut initialisiert wird?
Ein Attribut ist letztlich nichts anderes, als der Verweis über einen Namen auf ein Objekt. Ob dieses Objekt eine Liste, ein String, eine Funktion/Methode oder sonstwas ist, spielt keine Rolle. Nachdem Du ein Klassenattribut erstellt hast kannst Du über den Namen des Attributs auf das verwiesene Objekt und all seine Eigenschaften zugreifen.
In meinem Beispiel übergebe ich beim Erstellen der 'Damper'-Exemplare unter anderem die Methode 'Car.force', die innerhalb der 'Damper.__init__'-Methode an das Klassenattribut 'Damper.load' gebunden wird. Damit verhält sich 'Damper.load' wie die Methode 'Car.force', weil eben (der Name) 'Damper.load' nichts anderes ist als ein Link zu 'Car.force'.

mutetella

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 18:14
von BlackJack
@schneitzmaster: Das lokale Namen nicht exportiert werden ist implizit klar, denn es sind ja lokale Namen. Da muss man nichts kennzeichnen und ich habe dazu auch nichts in dem Wikibook-Text gefunden. Dort geht es um Attribute von Objekten und nicht um lokale Namen.

@mutetella: Statt Klassenattribut meinst Du IMHO jeweils Instanzattribut. Jetzt mal davon abgesehen dass es zwei „Arten” von Methoden gibt — ungebundene auf der Klasse tatsächlich als Klassenattribut, und gebundene Methoden auf Exemplaren/Instanzen.

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 18:32
von schneitzmaster
@BlackJack:
Ja es ist klar das lokale Variablen nicht exportiert werden ist klar. Dennoch ist auf der Wiki-Seite unter der Überschrift "Privat - mehr oder weniger" als erster Satz folgendes zu finden:
Um gegenüber den Nutzern einer Klasse anzudeuten, dass bestimmte Methoden oder Attribute privat sind, also nicht nach außen exportiert werden sollen, stellt man ihnen einen Unterstrich (_) vorran
Ich interpretiere das so, dass man vor Variablen/Attributen die nicht exportiert werden einen unterstrich setzt.
Aber vielleicht vermische ich gerade Attribute und Variablen (oh man, ich weiß schon warum ich kein Informatik studiert habe).
so long...

P.S.: Mein Code funktioniert jetzt so wie er soll und das hauptsächlich durch eure Hilfe!
Danke dafür noch mal an alle die sich hier so rege beteiligt haben.

Re: Datenweitergabe zwischen Instanzen durch Vererbung?

Verfasst: Freitag 25. Januar 2013, 18:37
von BlackJack
@schneitzmaster: Attribute sind die Werte auf die man mit dem Punkt-Operator oder `getattr()` zugreift. Variable ist ein recht schwammiger Begriff, den man manchmal auch für Attribute verwendet und für Namen auf Modulebene (Attribute des Modul-Objekts) und lokale Namen.