Klassen-Variable initiieren?

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.
Antworten
efix
User
Beiträge: 43
Registriert: Samstag 7. Dezember 2019, 20:59

Moin,

ich mache gerade zum erstmal was mit Klassen in Python und ich wollte mal fragen ob das so richtig ist wie ich die Variabeln initiiere? Oder wie ihr das machen würdet...

Code: Alles auswählen

class Calculate:
    zahl1 = 0
    zahl2 = 0
    
    def __init__(self):
        self.zahl1 = self.getzahl()
        self.zahl2 = self.getzahl()
        
    
    def getzahl(self):   
        return float(input("Geben Sie eine Zahl ein: "))


cal = Calculate()

print(cal.zahl1)
Also funktionieren tut es!

Viele Grüße
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist falsch so, weil deine Deklarationen auf Klassen-Ebene (also direkt unter der class-Instruktion) nicht das sind, was du glaubst das sie sind. Dabei handelt es sich naemlich *nicht* um Instanzvariablen, was du eigentlich willst. Sondern um Klassenvariablen, die sich *alle* Instanzen deiner Klasse teilen. Man sieht leider draussen gelegentlich Code, der das so macht, aber der ist ueblicherweise falsch.

Die Details hier sind subtil und vielfaeltig, aber die Faustregel ist ganz einfach: ALLER Zustand, den das Objekt haben soll, MUSS in __init__ angelegt werden. Keinerlei Instruktionen auf Klassenebene, ausser Methoden.
efix
User
Beiträge: 43
Registriert: Samstag 7. Dezember 2019, 20:59

Danke für die Antwort! Ich kann mir das so noch nicht vorstellen. Kannst du mir ein Beispiel zeigen wie es richtig ist dann verstehe ich das besser...
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Funktionen werden nach Tätigkeiten benannt, Klassen nach Dingen. Also statt `Calulate` `Calculation`. Abkürzungen benutzt man nicht.
`getzahl` benutzt `self` gar nicht, warum ist das dann eine Klassenmethode? `zahl` ist auch das einzig deutsche Wort. Bleib bei einer Sprache bei der Benennung. Die Klasse ist sehr kurz, da kommt sicher noch was dazu, so dass man noch nicht sagen, ob bei Deiner Aufgabe überhaupt eine Klasse nötig ist.

Code: Alles auswählen

def get_number():   
    return float(input("Geben Sie eine Zahl ein: "))

class Calculation:
    def __init__(self):
        self.number1 = get_number()
        self.number2 = get_number()

calculation = Calculation()

print(calculation.number1)
efix
User
Beiträge: 43
Registriert: Samstag 7. Dezember 2019, 20:59

Ok. Ich denk drüber nach. Aber warum definierst du Funktion außerhalb der Klasse?
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Frage sollte anders herum gestellt werden, warum hast Du eine Funktion in eine Klasse gesteckt, obwohl sie nichts von der Klasse braucht.
efix
User
Beiträge: 43
Registriert: Samstag 7. Dezember 2019, 20:59

Aber die Funktion wird doch von dem Objekt beim initiieren benutzt damit ist sie doch ein wesentlicher Teil der Klasse, oder nicht? Kann ich so noch gar nicht sagen...
Ich denk drüber nach warum...
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Auch hier wieder: wenn die Funktion keinen Zugriff auf self benoetigt, muss oder sogar sollte sie *nicht* Teil der Klasse sein.
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@efix: Es werden auch die Funktionen `input()` und `float()` beim Initialisieren benutzt, die sind ja auch nicht in der Klasse definiert. Und falls Du eine weitere Klasse schreibst, wo der Benutzer Zahlen eingeben muss, dann müsstest Du dort nach der Logik die gleiche ”Methode” noch mal schreiben, statt dass Du bereits eine Funktion hast, die in beiden Klassen benutzt werden kann.

Es gibt seltene Fälle in denen eine Funktion so stark an eine Klasse gebunden ist, dass man sie als „statische Methode“ in die Klasse schreibt. Dann aber auch ohne das unbenutzte `self` und mit `staticmethod()` dekoriert.

Es ist übrigens auch ungewöhnlich Benutzerinteraktion in eine `__init__()` zu stecken. Überhaupt hält man die `__init__()` oft eher schlank/dumm, weil es das Testen und in anderen Kontexten verwenden einfacher macht, wenn sich leicht Exemplare erstellen lassen ohne zu viele Abhängigkeiten ”nach draussen” zu haben, also insbesondere Eingaben, aber auch Ausgaben.

Aufbauend auf dem Beispiel von Sirius3 beispielsweise:

Code: Alles auswählen

#!/usr/bin/env python3


def get_number():
    return float(input("Geben Sie eine Zahl ein: "))


class Calculation:
    def __init__(self, number_a, number_b):
        self.number_a = number_a
        self.number_b = number_b


def main():
    calculation = Calculation(get_number(), get_number())
    print(calculation.number_a)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten