Funktiosaufruf in gpiozero ohne Klammern?

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Bravragor
User
Beiträge: 5
Registriert: Mittwoch 5. Januar 2022, 09:37

Mahlzeit zusammen,

erstmal kurz zum Hintergrund,
mein Sohn (8Jahre) hat zu Weihnachten einen PI400 von meinem Bruder bekommen. Junior ist auch total angetan vom Programmieren in Python und arbeitet gerade das beilegte Buch durch.
Darin soll man ein Reaktiosspiel mit zwei Tastern und einer LED programmieren.
Ich für meinen Teil bin nicht wirklich fit in Python, so gar nicht.

Auf jeden Fall hatten wir zwei Probleme mit dem Code im Buch, welche wir aber lösen konnten.
Was mich aber wundert ist, warum manchmal Funktionen in GPIOzero ohne Klammern aufgerufen werden.

In unseren Fall ging es um folgendes:

Code: Alles auswählen

button = Button(2)

def say_hello():
    print("Hello!")
    
button.when_pressed = say_hello
Den Code habe ich jetzt von https://gpiozero.readthedocs.io/en/stable/recipes.html kopiert, da der eigentliche Code halt gerade auf dem PI von Junior ist und ich ihn gerade nicht auswendig weiß.
Auf jeden Fall wäre für mich logisch gewesen die Funktion mit () hinter say_hello aufzurufen da mit dem einfachen = je eigentlich einer Variable ein Wert zugeordnet wird.

Würde mich freuen wenn mich hier wer über die Art der Funktionsaufrufe in Python aufklären könnte.

Besten Dank
Mario
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist in diesem Fall nicht logisch, weil das benutzen vom klammern an dieser Stelle eine Aufruf der Funktion darstellt. Sofort. Das ist aber nicht, was man will. Man will eine Funktionreferenz an when_pressed binden, so das *wenn* der Knopf gedrückt wurde, erst die Funktion aufgerufen wird.
Bravragor
User
Beiträge: 5
Registriert: Mittwoch 5. Januar 2022, 09:37

Ok, dann muss ich mir dass mit den Funktionsaufrufen vielleicht nochmal ganz genau anschauen.
Für mein Verständnis wartet dass .when_pressed auf den Tastendruck und ruft dann die Funktion auf.
Leider ist sowas alles in dem Buch nicht wirklich gut erklärt und das Programm läuft auch nicht wie gewünscht wenn man es dann fertig hat.
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dein Verständnis vom when_pressed ist ja korrekt. Aber wenn irgendwo im Code

funktionsname()

steht, dann wird nunmal in dem Moment die Funktion aufgerufen. Da gibt es kein „ach nee, hier meine ich aber, dass es erst später beim Knopfdruck passieren soll“.
Bravragor
User
Beiträge: 5
Registriert: Mittwoch 5. Januar 2022, 09:37

Danke.
Werde es Junior erstmal so erklären und selber nochmal genau nachlesen.
Hab gesehen, dass es in der Bibliothek ja einige Beispiele gibt.
Mit GPIOs habe ich bisher nur etwas am Arduino gearbeitet und da gab es solche Aufrufe in meinen Fällen nicht.

Haben gerade gemerkt, dass das Buch eh nur bedingt PI400 tauglich ist, da man das ganze zum Thema Kamera ja gar nicht bearbeiten kann.
Jetzt gerade haben wir erstmal den Sense HAT und ein Verlängerungskabel für die GPIO gestellt.
Aber das ist ein ganz anderes Thema.
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nachtrag: wenn du sagst “wartet auf den Tastendruck”, dann ist damit nicht gemeint, dass die Ausführung in diese Zeile stehen bleibt! Sonst könntest du ja niemals mehrere Tastendrücke abfragen. Sondern das meldet eine Rückrufaktion (eben say_hello) an, und dann gehts gleich weiter. Da fehlt das pause() oder Ähnliches am Ende, welches im echten Programm da ist.
Bravragor
User
Beiträge: 5
Registriert: Mittwoch 5. Januar 2022, 09:37

Das war ja eines unserer Probleme, das pause() war nicht im originalen Programm, weder wurde es in der Anleitung erklärt/geschrieben noch war es im Beispielcode wie das fertige Programm aussehen soll.
Tante Google hat uns da aber schon geholfen.
Mussten ja erst noch die Bibliothek "signal" importieren und dann halt das pause() drunter schreiben.
Hier war ich das erste mal verwundert, da mir klar, dass das Programm so zum Ende durchgeht und niemand in der Lage ist so schnell passend nen Knopf zu drücken.
Ich war gestern noch auf der Homepage vom Autor und dort kann man das Buch im englischen Original kostenlos runter laden und auch da fehlte das pause() am ende des Programms.
Aber das ganze hatte auch einen großen Vorteil.
Ich wusste zum Beispiel nicht, dass mit def eine Funktion definiert wird und so.
Leider war der Code im Buch kein bisschen kommentiert! Also musste ich mich da eh erstmal zurechtfinden. Da konnte ich Junior gut zeigen, wie wichtig es ist, seinen Code zu kommentieren. Hoffe er beherzigt das ab jetzt.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Bravragor: Um noch mal auf dieses Zitat zu kommen:
Auf jeden Fall wäre für mich logisch gewesen die Funktion mit () hinter say_hello aufzurufen da mit dem einfachen = je eigentlich einer Variable ein Wert zugeordnet wird.
Genau das passiert da ja auch — durch das ``=`` wird dem Attribut `when_pressed` ein Wert zugeordnet. Funktionen sind Werte. Man kann die nicht nur aufrufen sondern auch an Namen zuweisen, in Datenstrukturen stecken, als Argumente an andere Funktionen übergeben — halt alles was man allgemein mit Werten so machen kann.

(Also technisch gesehen ist `when_pressed` kein einfaches Attribut, da passiert bei der Zuweisung dann doch hinter den Kulissen noch etwas zusätzliches, aber das ist für das Beispiel hier jetzt nicht relevant, weil sich das, was da passiert, nicht auf den Aufruf von dem Wert bezieht, den man zuweist.)

Bei dem Kommentieren hast Du ihm hoffentlich keinen Bärendienst erwiesen, denn guter Code kommt mit wenig bis gar keinen Kommentaren aus. Insbesondere kommentiert man nicht *was* der Code macht, denn das steht da ja bereits als Code. Man kommentiert warum der das so macht wie er es macht, sofern das nicht offensichtlich ist. Und offensichtlich ist erst einmal alles was in der Dokumentation der Programmiersprache und der verwendeten Bibliotheken steht. Denn sonst würde man ja über Kommentare dauernd die Dokumentation von dort in die eigenen Programme kopieren. Das ist sinnlose Arbeit und wenn man nicht 1:1 kopiert sondern irgendwie selbst zusammenfasst, eine zusätzliche Quelle von Fehlern und potentieller Verwirrung.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Bravragor
User
Beiträge: 5
Registriert: Mittwoch 5. Januar 2022, 09:37

Ahh, danke für die Info zur Zuweisung. Also weise ich in dem Fall dem Attribut .when_pressed im Grunde die ganze Funktion say_hello() zu welche dann logischer Weise ausgeführt wird sobald das when_pressed passiert.

Also das mit dem Kommentaren ist so eine Sache, ich bin absolut nicht der Meinung dass der Code genug Dokumentation ist. Aber hier scheiden sich die Geister und das Thema ist ähnlich der Helmfrage in Fahrradforen.
Junior ist acht Jahre und da finde ich es für ihn schon gut, wenn er sich sowas in den Code schreibt. Aber wie gesagt, Einstellungssache.
Antworten