Seite 1 von 1

Variable in Klasse Automatisch ändern?

Verfasst: Freitag 13. November 2009, 16:07
von Purefranky
Tach Leute.
Sorry, ich weiß einfach nicht, unter welchem sinnvollen Begriff ich das suchen soll, da gibt´s sicher nen Fachbegriff zu.

Geht um Folgendes, ich hab ne Klasse

Code: Alles auswählen

Class Kraft():
    x=0.0;
    y=0.0;
    gesamt=0.0;
    winkel=0.0;
Jetzt würd ich gerne "gesamt" und "winkel" errechnen lassen, sobalt x bzw. y geändert werden. Mir schwirrt im Kopf rum, dass man das automatisch lösen lassen kann, indem man es in der Klasse einträgt, aber vll. verwechsel ich´s auch mit ner anderen Sprache.

Also kurzum, geht das?

Mfg PureFranky

Verfasst: Freitag 13. November 2009, 16:12
von nemomuk
Wenn ich mir ansehe, was du da so machst, glaube ich wirklich, dass du eine andere Sprache meinst. Aber das was du da willst, würde man wahrscheinlich mit __setattr__ umsetzen.

Verfasst: Freitag 13. November 2009, 16:29
von Purefranky
Na das geht ja flott hier :D .
Danke, ich werd mal schaun, was sich damit machen lässt.
Bisher komm ich immer in ne dauer-Rekursion, kann ich den Aufruf von __setattr__ verhindern? Hier mal ein Beispiel:

Code: Alles auswählen

class Dings():
    wert1=0;
    def __setattr__(self, name, value):
          if name=='wert1':
             self.wert1=value;
             self.wert2=self.wert1**2;
             print(name);
             print('Jo');
             return value;
    wert2=0;

ls=Dings();
ls.wert1=5;
print(ls.wert1);
print(ls.wert2);
ls.wert1=90;
print(ls.wert1);
print(ls.wert2);

Verfasst: Freitag 13. November 2009, 16:38
von Defnull

Code: Alles auswählen

class Kraft():
    def __init__(self, x=0., y=0.):
        self.x = x;
        self.y = y;

    @property
    def gesamt(self):
        return ...

    @property
    def winkel(self):
        return ...

Verfasst: Freitag 13. November 2009, 16:40
von nemomuk
Jo, das wäre definitiv schöner, aber mit dem Dekorator kommt man beim setzen von Werten nicht sehr weit...

Des Weiteren bist du dir im klaren, was der Unterschied zwischen Klassen und Instanzvariablen ist? Ich denke nicht, dass du die Winkel aller Instanzen ändern willst, sondern nur einer Bestimmten.

Verfasst: Freitag 13. November 2009, 16:51
von HWK

Code: Alles auswählen

    def __setattr__(self, name, value):
        self.__dict__[name] = value
        if name == 'wert1':
            self.wert2 = self.wert1 * self.wert1
MfG
HWK

Verfasst: Freitag 13. November 2009, 17:03
von CM
Jetzt würd ich gerne "gesamt" und "winkel" errechnen lassen, sobalt x bzw. y geändert werden.
Ich unterstelle mal, dass x und y Koordinaten im Raum sind. In dem Fall frage ich mich: Sind Raumpunkte Eigenschaften einer Kraft? Wenn ich Simulationen gerechnet habe, hatte ich meist ein Objekt mit best. Eigenschaften im Raum auf das Kräfte gewirkt haben. Das aber setzt ein grundsätzlich anderes Design voraus.

Das nur nebenbei - vielleicht liege ich mit meiner Vermutung ja auch völlig daneben.

HTH
Christian

Verfasst: Freitag 13. November 2009, 18:10
von pillmuncher
Purefranky hat geschrieben:

Code: Alles auswählen

class Dings():
    wert1=0;
    def __setattr__(self, name, value):
          if name=='wert1':
             self.wert1=value;
             self.wert2=self.wert1**2;
             print(name);
             print('Jo');
             return value;
    wert2=0;

ls=Dings();
ls.wert1=5;
print(ls.wert1);
print(ls.wert2);
ls.wert1=90;
print(ls.wert1);
print(ls.wert2);
Bitte tu dir selbst einen Gefallen und verwende keine ; am Zeilenende. Das macht man in Java/C/C#/C++/..., aber nicht in Python. Außerdem werden auch Attribute (so heißen Member-Variablen in Python) nicht so eingeführt wie du das machst, defnull hat dir schon gezeigt wie es richtig geht, nämlich in einer __init__-Methode. Auch hier gilt: Python ist nicht Java.

Zu deinem Problem hat dir defnull schon alles gezeigt was du brauchst. Was mich aber doch interessiert: Warum schreibst du nicht einfach eine Methode?

Code: Alles auswählen

>>> class Breakfast(object):
...     def __init__(self, beans, ham, spam):
...         self.beans = beans
...         self.ham = ham
...         self.spam = spam
...     def order(self):
...         if self.beans:
...             return 'Baked beans are off!!'
...         else:
...             return 'Ham: %s, Spam: %s' % (self.ham, self.spam)
...
>>> breakfast1 = Breakfast(1,2,3)
>>> breakfast2 = Breakfast(0,1,2)
>>>
>>> print breakfast1.order()
Baked beans are off!!
>>> print breakfast2.order()
Ham: 1, Spam: 2
>>> breakfast2.ham = 4
>>> print breakfast2.order()
Ham: 4, Spam: 2
Gruß,
Mick.

Verfasst: Freitag 13. November 2009, 19:06
von Purefranky
Hehe, is ja richtig voll geworden hier :lol: .

@CM:
Jo, du hast es erraten, ich wollte mich ma an nem FEM-Löser versuchen, mein Prof hat son Ding geschrieben, will aber den Quelltext nich rausrücken, also schreib ich ihn mir selbst, wenn ich einmal verstanden hab, wie ein Programm arbeitet, versteh ich besser, was ich in der Klausur mache.
Bin aber in Python recht eingerostet und hab auch nie was großes damit gemacht. Es soll aber nur der Löser in Python geschrieben werden, Netzgenerator und Post-Prozessor sollen in PureBasic entstehen. Da schreib ich den Quelltext blind runter und dann geht dat schneller. :roll:

@Pillmuncher: Java hab ich nie programmiert :wink:
Kommt noch von Delphi, ebenfalls Studium, hab beides durchnander geschmissen und dachte daher , das müsste so sein, also hab ich´s genutzt und nicht weiter drauf geachtet, ob Python meckert. Aber danke für den Tip :wink:
Zum Thema Methode: So'n FEM-Löser (gut, meiner wird nur ein kleiner, aber einer mit großen Netzen für richtige Geometrien und 3D) braucht recht viel Rechenaufwand. Und wenn ich 4 mal length aufrufe, geht es um einiges schneller, wenn ich erst einen festen Wert errechne und diesen dann in einer Variable speicher, als wenn ich jedes mal neu errechne.
Da sollte sich Python nicht von anderen Sprachen unterscheiden, obwohl´s ne Scriptsprache ist, oder irre ich mich?

@Defnull: Danke für den Tip mit __init__. Klassen haben wir inner Vorlesung damals nicht besprochen :shock: (Traurig, aber wahr :x ), daher kenn ich mich damit nich aus.

So, also allgemein danke, ich hab es jetzt erstmal mit ner normalen Funktion, die ich aufrufen muss probiert, so geht auch nicht jedesmal rechenzeit verloren, wenn x oder y mehrfach geändert werden, bevor length aktualisiert werden muss.

Mfg und frohes coden weiterhin
PureFranky

Verfasst: Samstag 14. November 2009, 01:18
von Leonidas
SchneiderWeisse hat geschrieben:Jo, das wäre definitiv schöner, aber mit dem Dekorator kommt man beim setzen von Werten nicht sehr weit...
Doch, ich meine dass Python 2.6 auch Dekoratoren für das Schreiben von Attributen hat.

Verfasst: Samstag 14. November 2009, 01:58
von BlackVivi
Leonidas hat geschrieben:
SchneiderWeisse hat geschrieben:Jo, das wäre definitiv schöner, aber mit dem Dekorator kommt man beim setzen von Werten nicht sehr weit...
Doch, ich meine dass Python 2.6 auch Dekoratoren für das Schreiben von Attributen hat.
Oder mit @apply...

Code: Alles auswählen

class Example(object):
    @apply
    def myattr():
        doc = """This is the doc string."""

        def fget(self):
            return self._half * 2

        def fset(self, value):
            self._half = value / 2
 
        def fdel(self):
            del self._half

        return property(**locals())

Verfasst: Samstag 14. November 2009, 06:08
von pillmuncher
@Purefranky: Ich glaube du suchst das hier (geht ab Python 2.6):

Code: Alles auswählen

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])

class Kraft(object):

    def __init__(self, point=None, x=0.0, y=0.0):
        if point:
            self._x = point.x
            self._y = point.y
        else:
            self._x = x
            self._y = y
        self._update()

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, val):
        self._x = val
        self._update()

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, val):
        self._y = val
        self._update()

    def _update(self):
        self.gesamt = ...
        self.winkel = ...


p = Point(x=3.7, y=4.5)
f = Kraft(point=p)
print f.x, f.y, f.gesamt, f.winkel

f.x = 7.1
f.y = 2.4
print f.x, f.y, f.gesamt, f.winkel

f1 = Kraft(x=6.2, y=3.3)
print f1.x, f1.y, f1.gesamt, f1.winkel
Für ... musst du halt einfügen was noch fehlt.

Gruß,
Mick.

Verfasst: Samstag 14. November 2009, 07:26
von nemomuk
Leonidas hat geschrieben:
SchneiderWeisse hat geschrieben:Jo, das wäre definitiv schöner, aber mit dem Dekorator kommt man beim setzen von Werten nicht sehr weit...
Doch, ich meine dass Python 2.6 auch Dekoratoren für das Schreiben von Attributen hat.
Mhm, ich sehe es gerade... kannte ich bisher nicht, mag auch an meinem 2.5 liegen.

Verfasst: Samstag 14. November 2009, 18:57
von HWK
@pillmuncher: Gerade wenn es um mehrere Attribute geht, funktioniert es mit __setattr__ m.E. einfacher und auch < Python 2.6:

Code: Alles auswählen

    def __setattr__(self, name, value):
        self.__dict__[name] = value
        if name in ('x', 'y'):
            self.gesamt = ...
            self.winkel = ...
MfG
HWK