Funktionen in Klassen

  • Das leidige Thema und ich hab es immer noch nicht begriffen.


    Mein Problem, wie kann ich eine Funktion einer Klasse aus einer anderen Klasse aufrufen?

    Hier mal ein Stück code...

    Vielleicht schafft es einer mir dies an diesem Bsp. Idiodensicher zu erklären


  • Zum Beispiel so:


  • Hallo,


    Tell : Das Beispiel ist IMHO nicht richtig. Wenn du mit Vererbung arbeitest, brauchst du in der Klasse keine Instanz der anderen Klasse anlegen:


    Streifenhase : was du denn genau vor? Dein Code ist... komisch. In der Klasse `PrintPicture` legst du 2x `self.geometry` an, das ist 1x zu viel. Die format-Methode macht an der Stelle keinen Sinn, da kannst du direkt den String schreiben.

    In der Klasse `MainWindow` überschreibst du `geometry` und `configure`.


    `configure` ist ein ungünstiger Name, weil ein Attribut nichts tut und von daher ein Tun-Wort als Name wenig aussagekräftig ist.

    Bei `attributes` würde man IMHO eher eine Liste von Attributen erwarten. Aktuell hast du "nur" ein implizit generiertes Tupel.


    Gruß, noisefloor

  • Hallo,

    noisefloor : Für mich sieht das aus, als wären "geometry" und "configure" von tk.Toplevel geerbte Methoden.

    Kann ja / wird ja so sein. Aber deswegen braucht man a) `geometry` nicht 2x überschreiben und b) ist das `format` immer noch nicht sinnvoll an der Stelle :-)


    Gruß, noisefloor

  • Aber deswegen braucht man a) `geometry` nicht 2x überschreiben

    Nach meinem Verständnis wird im ersten Aufruf die Fenstergröße und im zweiten die Position gesetzt.

    und b) ist das `format` immer noch nicht sinnvoll an der Stelle :-)

    Da bin ich voll bei Dir.


    Das hier:

    `configure` ist ein ungünstiger Name, weil ein Attribut nichts tut und von daher ein Tun-Wort als Name wenig aussagekräftig ist.

    gilt dann allerdings nicht – zumal Streifenhase auf die Benennung keinen Einfluss hat.

  • Naja, die Bezeichner sind halt die Vorgaben von tkinter. Ich habe mich damit letztens auch erst wieder beschäftigt und tkinter ist -- wenn auch Python-Quasistandard für GUI-Anwendungen -- jedes Mal irgendwie eigenwillig, um nicht zu sagen "veraltet". Die Trennung bei geometry soll vermutlich die Fensterposition (1. Kommando) und die Fenstergröße (2. Kommando) auftrennen. Allerdings war/ist mir nicht bewusst, dass/ob das überhaupt funktioniert. Ich habe es jetzt nicht getestet, die Syntax des Parameters gäbe es aber sogar her...

  • Hallo,


    Zitat

    Nach meinem Verständnis wird im ersten Aufruf die Fenstergröße und im zweiten die Position gesetzt.

    Ja, wird wohl. Wenn das getrennte Setzen der Werte funktioniert ist da ja schön bzw. praktisch - stilistisch und vom Verständnis für Außenstehende aber eher fragwürdig...


    schlizbäda : Standard kann man so nicht sagen. Es wird halt bei der Installation von Python oft direkt mitinstalliert, d.h. die Nutzung ist am "einfachsten", weil man ja nichts mehr tun muss. Bei Kivy oder Qt muss man halt alles mögliche nachinstallieren - bekommt dafür aber auch ein moderneres & leistungsfähigeres Toolkit.


    Gruß, noisefloor

  • Ja, wird wohl. Wenn das getrennte Setzen der Werte funktioniert ist da ja schön bzw. praktisch - stilistisch und vom Verständnis für Außenstehende aber eher fragwürdig...

    Full ACK!

  • Soo ich melde mich mal wieder.


    Also mit der geomtry ist tatsächlich eins die größe das andere die possition.

    Ich stehe nach wie vor noch am Anfang mit Python und habe dadurch mit Sicherheit noch viele Fehler.

    Ein Buch habe ich mir jetzt nun endlich auch bestellt und hoffe das ich irgendwann mehr selbständig agieren kann.


    So jetzt noch mal zum eigentlichen:

    Ich wollte das ausführen aus einer anderen Klasse um ein Canvas Bild zu updaten.


    bin allerdings bisher gescheitert


    Ich würde noch mal einen Teil des Codes Posten vielleicht möchte sich einer das mal anschauen. gehe aber davon aus das noch mehr Fehler drin sind mir geht es aber erst mal darum das Canvas beim auslösen des PIN27 erneuert wird und zwar mit dem aktuellsten Bild aus dem angegebenen Verzeichnis.


    class PrintPicture ertellt ja ein Fenster, durchsucht das Verzeichnis und erstellt dann ein Bild im Fenster.


    class MainWindow, bestimmt die GPIO´s und dessen Funktionen



  • Aaalso:


    Mir ist schon klar, dass Du Deinen Beispielcode zusammen kopiert hast, für Einsteiger nichts Verwerfliches.

    Aber zuerst mal solltest Du bei Deinen import-Anweisungen Ordnung reinbringen. Es gibt (mindestens) vier Syntaxvarianten von import:


    import modulname

    Diese Anweisung liest das Modul ein. Alle darin mir def definierten Funktionen können über modulname.funktionsname(...) aufgerufen werden. Dies ist in meinen Augen die sauberste Variante, da man damit im Code immer sofort sieht, welche Funktion aus welchem Modul verwendet wird.


    import modulname as m

    Bei dieser Variante können die Funktionen von modulname über m.funktionsname(...) aufgerufen werden. Bei klaren Namen anstatt einfach m kann dies die Lesbarkeit des Codes evtl. erhöhen.


    from modulname import f1, f2

    Die Funktionen f1 und f2 des Moduls können ohne Voranstellen von modulname. aufgerufen werden. Ich persönlich bin davon kein Freund, da diese Schreibweise im späteren Code die Herkunft der (fremden) Funktionen f1 und f2 verschleiert, ist aber ohne * noch vertretbar.


    from modulname import *

    Hiermit werden alle Symbole aus modulname importiert, die nicht mit __ (zwei Unterstrichen) beginnen. Dies birgt bei mehrfacher Anwendung dieser Syntaxvariante die Gefahr, dass bei gleichen Bezeichnern, die in mehreren Modulen vorkommen, Konflikte entstehen, die sehr schwer zu finden sind! In meinen Augen ein echtes Unding, das man möglichst vermeiden muss!


    Abschreckendes Beispiel:

    Code
    1. from tkinter import *
    2. import tkinter as tk
    3. from tkinter import PhotoImage

    Was passiert? Du kannst auf alle Routinen von tkinter sowohl über tk.bezeichner als auch nur über bezeichner zugreifen! Am "besten" mischt man im folgenden Code beide Varianten für vollendete Unübersichtlichkeit.:(

    Die dritte Zeile wäre die ohne der ersten prinzipiell berechtigt, da sie nur den Teil PhotoImage zusätzlich sichtbar macht. Aufgrund des Vorhandenseins der ersten Zeile ist sie schlichtweg überflüssig, da die erste ja schon alle Bezeichner sichtbar macht.


    weiter:

    Wenn du eh das Modul PIL komplett importierst, würde ich jetzt nicht noch zusätzlich mit from die beiden Teile Image und ImageTk separat importieren, nur um den Teil PIL. weglassen zu können, zumal ja PhotoImage auch "Image"-Funktionen enthalten wird, die ähnliche Namen haben könnten (weiß ich jetzt im konkreten Fall nicht). Das stiftet jedoch leicht die oben beschriebene Unübersichtlichkeit und mögliche Inkonsistenzen des resultierenden Codes.




    Das for-Kommando in Zeile 29 enthält eine falsche Stringbegrenzung: Zwei Anführungszeichen vor dem Suchpfad!


    In Zeile 28 initialisierst Du die Variable found vorbildlich mit None, machst aber nach der for-Schleife keine Fallunterscheidung vor Zeile 36, ob eine Datei gefunden wurde oder nicht (z.B. leeres Verzeichnis). Dies führt höchstwahrscheinlich zu Folgefehlern beim Befüllen des canvas-Widgets.


    def Interrupt_event ab Zeile 74 ist auch nicht konsistent:

    Sowohl im if- als auch im else-Zweig wird der gleiche String "Rising Edge..." ausgegeben :?:

    EDIT:

    ich würde die if-Abfrage so gestalten, dass ich zuerst den Parameter pin auf 27 prüfen würde und dann innerhalb des if-Zweiges, ob es eine steigende oder fallende Flanke war...

    To make it better just tux it a little bit. (auf englisch haut dieses Wortspiel hin, da kann man aus fast jedem Hauptwort ein gleichlautendes Tunwort bilden)

    Hofei's guide to: Wie frage ich nach Hilfe? STF's advice to: NOOBS oder nicht? meigrafd's summary to: nützliche Links 

    3 Mal editiert, zuletzt von schlizbäda () aus folgendem Grund: ein paar weitere Fehler gefunden

  • from modulname import *

    Hiermit werden alle Symbole aus modulname importiert, die nicht mit __ (zwei Unterstrichen) beginnen.

    Korrektur: es werden alle in __all__ aufgelistete "Symbole" importiert (dann ggf. auch solche, die mit __ beginnen), sofern vorhanden (und das ist nicht unüblich). Nur wenn __all__ nicht existiert, gilt die von dir genannte Regel, wobei noch ein klitzekleiner Fehler enthalten ist: auch Bezeichner mit einem führenden Unterstrich werden nicht importiert. ;)

  • Hallo,


    also ich sehe eigentlich gar keinen Grund, warum das in zwei Klassen aufgeteilt sein soll... Beide Klassen haben in der gezeigten Version je eine Methode - dann kann man sich die Klasse auch sparen und "nur" eine Funktion schreiben, dabvs kommt hier auf's selbe raus.


    Das in der Klasse `MainWindow` `GPIO.setmode()` aufgerufen wird ist IMHO falsch, weil man den Befehl nur genau 1x aufrufen kann, sonst gibt's eine Fehlermeldung. Heißt aber dann auch, dass man immer nur genau eine Instanz der Klasse anlegen kann - was nicht hier vielleicht nicht stört, aber grundsätzlich nicht sinnvoll ist, weil man grundsätzlich Klassen beliebig oft instanzieren können sollte.


    Streifenhase : GUI Programmierung kannst du mit Python nur erfolgreich machen, wenn du das Konzept der Objektorientierung verstanden hast, respektive, wofür Klassen, Methoden, Attribute, Instanzen von Klassen etc sind. Ohne geht das nicht. Und ohne das Verständnis brauchst du auch mit Vererbung von eigenen Klassen oder Mixins nicht anfangen.

    Das soll dich von deinem Projekt natürlich nicht abhalten, aber Programmieren ist nicht raten und Programmieren ist auch nicht Copy&Paste gepaart mit der Hoffnung, dass es klappt. Bei bestimmten Sachen musst du halt die Zeit investieren, sie vernünftig zu lernen, damit die sie später erfolgreich anwenden kannst.


    Gruß, noisefloor

  • Danke, für die Tips ich werde mir diese auch zu Herzen nehmen.

    Aber wenn man keinen hat der es einem richtig erklären kann ( am eigenem Bsp.) ist das schwer.

    Wie gesagt ich hab mir ein Buch bestellt und hoffe das ich damit weiter komme.


    Nichts desto trotz möchte ich mich auch so damit beschäftigen weil auch wenn ich Fehler mach und Sachen zusammensetze bringt mich das weiter.


    Kleine Fortschritte kann ich selber ja auch feststellen.


    Trotzdem würde ich noch mal kurz auf das Canvas Thema zurück kommen.


    Habe versucht einen kleinen Code zu schreiben in dem ein Verzeichnis durchsucht wird und das Aktuellste Bild nimmt.

    Dazu eine Funktion die dann wieder das Verzeichnis durchsucht (habe jetzt nur mal ein anderes Format gewählt) "bis hierhin auch alles gut"


    aber ich bekomme es nicht hin das das alte mit dem neuen ersetzt wird.


    Währe Super wenn wir das noch hinbekommen würden, dann könnte ich mich die nächsten Wochen mit meinem Buch was hoffentlich nächste Woche kommt...