Seite 1 von 1

Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 11:02
von Antrazith
Nocheine Anfaengerfrage...

Nachdem ich eine Klasse initialisiert habe, und die noetigen Variablen uebergeben habe, moechte ich ein paar Werte berechnen. Diese sollen innerhalb der Klasse verwendet werden, um weitere Werte zu berechnen. In meinem Beispiel habe ich 4 Werte von einem T-Querschnitt uebergeben, und damit kann ich die Flaeche ausrechnen. Dieses Areal verwende ich dann um weitere Berechnungen innerhalb der Klasse durchzufuehren.

Der Kode funktionert jetzt allerdings nicht, weil ich in der methode "area()" nicht "area(self)" angegeben habe. Dadurch hat die Methode offensichtlich keinen Zugriff auf die 4 Ausgangsparameter. Ich koennte das natuerlich aendern, nur muss ich dann in allen weiteren Formeln immer (self) uebergeben.

Kann ich das irgendwie umgehen? Die Frage ist eigentlich, wie bekommen meine Methoden zugriff auf die 4 Hauptvariablen b, h, hw, hf (bzw. _b, _h, _bw, _hf) ohne dass ich die immer uebergeben muss?

Code: Alles auswählen

class T:
    """T-section properties"""
    _h: float
    _b: float
    _bw: float
    _hf: float

    type: str = 'T'

    def __init__(self, b: float, h: float, bw: float, hf: float):  # signals MyOwnException
        self._b = b    # total width
        self._h = h    # total self.height
        self._bw = bw  # beam width
        self._hf = hf  # slab thickness
        if self._b * self._h <= 0 | (self._bw > self._b) | (self._hf > self._h) | (self._bw * self._hf <= 0):
            raise Exception('T-section: impossible geometry data')

    @property
    def b(self):
        """total width"""
        return self._b

    @property
    def h(self):
        """total height"""
        return self._h

    @property
    def bw(self):
        """beam width"""
        return self._bw

    @property
    def hf(self):
        """slab thickness"""
        return self._hf

    @property
    def area():
        """Area of section"""
        return self._h * self.bw + self._hf * (self._b - self._bw)

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 11:29
von __blackjack__
@Antrazith: Methoden haben immer `self` als erstes Argument. Ich verstehe Dein Problem damit gerade nicht. Du musst das nicht übergeben, das wird bei Methoden automagisch übergeben.

Den Typannotationmist würde ich weg lassen. Wenn Du Java verwenden möchtest, dann verwende Java. ;-)

Und die `_` bei den Attributen auch, dann kannst Du auch die ganzen `property`\s weglassen und das ist alles gleich viel kürzer.

`T.type` ist überflüssig, die Klasse selber hat ja schon den Typ. Oder wozu brauchst Du das? Es wäre auch `T.TYPE`, denn der Wert ist ja Konstant.

Wenn man Namen mit einem Kommentar erklären muss, sollte man über bessere Namen nachdenken. Statt ein- oder zweibuchstabige Abkürzungen, die dann im Kommentar ausgeschrieben sind, sollte man gleich den richtigen Namen verwenden.

Das Bitweise ``|`` ist kein Ersatz für ``or``. Das bedeutet für den Leser etwas anderes, hat für diesen Zweck eine ungünstige Priorität gegenüber den anderen Operatoren, und es wird auch keine Kurzschluss-Auswertung gemacht.

Über 180 Zeichen pro Zeile ist furchtbar lang. Üblich sind 80.

Code: Alles auswählen

class TSection(object):

    def __init__(self, total_width, total_height, beam_width, slab_thickness):
        self.total_width = total_width
        self.total_height = total_height
        self.beam_width = beam_width
        self.slab_thickness = slab_thickness
        if (
            self.total_width * self.total_height <= 0
            or self.beam_width > self.total_width
            or self.slab_thickness > self.total_height
            or self.beam_width * self.slab_thickness <= 0
        ):
            raise Exception('T-section: impossible geometry data')

    @property
    def area(self):
        return (
            self.total_height * self.bw
            + self.slab_thickness * (self.total_width - self.beam_width)
        )

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 19:56
von Antrazith
Recht herzlichen Dank fuer die Tips, und ein paar schnelle Antworten.

Die Typeannotation kommt daher, weil ich die Vorschlaege von PyCharm akzeptiert habe. Ich muss mich erst daran gewoehnen, dass man in Python die Variablen offensichtlich nicht vorher definieren muss.
Ansonsten schaut der Kode ja ziemlich kurz und einfach aus, und vor allem verstaendlich.

Bei einer Sache bin ich allerdings noch am ueberlegen, das betrifft die Namenskonvention der Methoden. Ich verstehe dass alles kleingeschrieben sein sollte, und ausgeschrieben. Wenn man mit Formeln arbeitet, ist das allerdings ziemlich muehsam. Eine recht einfache Formel wie b * h^2 / 6 wird dann zu width * height**2 / 6. Das geht ja noch, aber wenn dann die Formel schon in kurzschreibweise ziemlich lang wird, wird's umstaendlich.

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 20:07
von Sirius3
Verständlicher wird eine Formel durch einbuchstabige Namen aber auch nicht. Wenn eine Formel zu lang wird, dann speichert man Zwischenergebnisse in aussagekräftigen Variablen.

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 21:42
von __blackjack__
@Antrazith: Definieren muss man alles was man verwendet bevor man es verwendet. Man muss nur keine Variablentypen deklarieren. Auch die Typannotationen sind keine Deklaration für den Compiler sondern erst einmal nur eine Absichtserklärung des Programmierers. Python selbst tut damit nichts weiter ausser die Informationen in den Objekten zu speichern. Da können sie dann IDEs und andere Werkzeuge auslesen und was damit machen.

Das Problem ist einfach das Typannotationen von Anfängern in der Regel zu einschränkend sind. Zum Beispiel bei Deiner Klasse könnte man ja eigentlich auch etwas anderes als Gleitkommazahlen als Werte übergeben. Beispielweise `decimal.Decimal`-Objekte oder `fractions.Fraction`-Objekte. Beides in der Standardbibliothek. Oder Numpy-Arrays. Oder Werte die mit einer Längeneinheit aus dem `quantities`-Modul multipliziert wurden, also vom Typ `Quantity` sind. Oder…

Beispiel:

Code: Alles auswählen

In [82]: print(TSection(50 * cm, 30 * cm, 42 * cm, 23 * cm).area)
1444.0 cm**2

In [83]: print(TSection(50 * cm, 30 * cm, 42 * cm, 23 * cm).area.simplified)
0.1444 m**2
Solchen Code würde eine statische Typprüfung dann anmeckern obwohl der wunderbar funktioniert und man weiss halt wenn man das schreibt noch nicht welche Typen da alle Sinn machen könnten, denn morgen könnte jemand einen völlig neuen Datentyp schreiben der in dem Kontext auch Sinn machen könnte.

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 22:04
von kbr
@Antrazith: Type Hints bieten Leuten Halt, die von statisch typisierten Sprachen kommen und in einer dynamisch typisierten Sprache wie Python gerne etwas mehr Sicherheit wünschen. Das ist quasi wie Fahrradfahren mit Stützrädern. Gute Fahrradfahrer aber fahren ohne Stützräder. Ohne diese kommt man jedoch besser voran.

Re: Klassen / Zugang zu Variablen

Verfasst: Freitag 27. Juli 2018, 22:54
von __blackjack__
Wobei man für die Sicherheit auch ein Werkzeug braucht das die Annotationen auf ihren Wahrheitsgehalt prüft. Wenn man das nicht regelmässig tatsächlich auch macht, dann bringt's auch keine Sicherheit da Warnhinweise dran zu pappen. :-) IMHO besser sind an der Stelle Unit-Tests die man regelmässig durchführt. Das kracht dann nicht nur bei falschen Typen, sondern auch wenn andere Fehler gemacht werden.

Re: Klassen / Zugang zu Variablen

Verfasst: Samstag 28. Juli 2018, 10:36
von Antrazith
Bin ziemlich sprachlos - kann man in Python mit Einheiten rechnen? Das waere ja wirklich ein Traum fuer jeden Ingenieur - sowas kenn ich bisher nur von Mathcad.

Gibt's da mehr Infos irgendwo?

Re: Klassen / Zugang zu Variablen

Verfasst: Samstag 28. Juli 2018, 10:47
von kbr
Im Prinzip geht das, indem Einheiten als Klassen angelegt und die erforderlichen Operatoren überladen werden. Aber ich vermute, Du hast 'Unit-Tests' falsch verstanden ;-)
Das sind Tests darauf, ob Dein Code korrekt funktioniert.

Re: Klassen / Zugang zu Variablen

Verfasst: Samstag 28. Juli 2018, 11:50
von __blackjack__
@Antrazith: Wie gesagt das `cm` ist aus `quantities`: https://pypi.org/project/quantities/