2

I'm learning python and gpio using the examples here: https://gpiozero.readthedocs.io/en/stable/recipes.html

I wanted to extend the code to more than one button and pass a parameter to a function (for example the button number). The code works for both buttons when I don't pass a parameter, but doesn't when I pass one. I'm sure it's related to the note here, but I don't know how to get around that. Here's the code that doesn't work, in fact it prints Hello! 1 then Hello! 2 without any buttons being pressed then does nothing when either button is pressed, but prints Goodbye! when either button is released. How do I fix the code to call the function with a parameter when either button is pressed? Thank you.

from gpiozero import Button
from signal import pause

def say_hello(button_number):
    print("Hello!", button_number)

def say_goodbye():
    print("Goodbye!")

button1 = Button(2)
button2 = Button(3)

button1.when_pressed = say_hello(1)
button1.when_released = say_goodbye
button2.when_pressed = say_hello(2)
button2.when_released = say_goodbye

pause()

Code that works based on the answer below:

from gpiozero import Button
from signal import pause

def say_hello(button_number):
    if button_number == 1:
        return lambda: print("Hello, Button 1!")
    if button_number == 2:
        return lambda: print("Hello, Button 2!")

def say_goodbye():
    print("Goodbye!")

button1 = Button(2)
button2 = Button(3)

button1.when_pressed = say_hello(1)
button1.when_released = say_goodbye
button2.when_pressed = say_hello(2)
button2.when_released = say_goodbye

pause()
1

So when_pressed wants a reference to a function, maybe something like

def say_hello(x):
    if(x == 1):
        return lambda: print("Pressed 1")

... and so on for other cases.

  • 1
    Thanks, that works. I'll have to go learn about lambdas now and why that worked and mine didn't. – T. M. Dec 10 '18 at 1:20
3

It is possible to use parameters with callback functions. See e.g. Documentation for button.when_pressed

This can be set to a function which accepts no (mandatory) parameters, or a Python function which accepts a single mandatory parameter (with as many optional parameters as you like). If the function accepts a single mandatory parameter, the device that activated will be passed as that parameter.

So the following code

from gpiozero import Button
from signal import pause

def say_hello(button):
    print(button.pin)

def say_goodbye():
    print("Goodbye!")

button1 = Button(20)
button2 = Button(21)

button1.when_pressed = say_hello
button1.when_released = say_goodbye
button2.when_pressed = say_hello
button2.when_released = say_goodbye

pause()

results in

GPIO20
Goodbye!
GPIO21
Goodbye!

(when pressing the appropriate buttons, of course)

So the button instance is always the first parameter. If you want to use additional parameters you can set the button instance manually:

from gpiozero import Button
from signal import pause

def say_hello(button, text = ""):
    print(text + str(button.pin.number))

def say_goodbye():
    print("Goodbye!")

button1 = Button(20)
button2 = Button(21)

button1.when_pressed = say_hello
button1.when_released = say_goodbye
button2.when_pressed = say_hello(button2, text = "Button 2 connected to ")
button2.when_released = say_goodbye

pause()

Pressing button 2 will result in

Button 2 connected to 21
  • 1
    My pleasure :-) – Dirk Dec 10 '18 at 18:31
  • Works as expected. You can even subclass the Button to pass any parameters for the callback using this technique – Woof Feb 23 at 20:37
1

You cannot pass a parameter to a callback function. You need separate functions for each callback.

  • Ok, more good things to learn, thanks. But in the working code above aren't I passing a parameter to the callback function? – T. M. Dec 10 '18 at 1:44
  • @T.M. Well NO. The lambda creates a new function which retains the calling scope. You are actually still creating separate functions. lambdas are an advanced topic, and not appropriate in a beginner program. By all means read about lambdas, but you need a lot of other knowledge tu understand them. – Milliways Dec 10 '18 at 2:44
  • 1
    You cannot pass a parameter to a callback function. That's not correct. See when.pressed doc – Dirk Dec 10 '18 at 11:38

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.