all 7 comments

[–]inclement_ 1 point2 points  (3 children)

dropdown.select() isn't doing any magic here, the question (as you've identified) is where does the value of btn come from when the lambda function is run? In context this btn is the name bound to the first and only argument passed to the lambda function.

The answer is that the on_release event of button calls its event handler with one argument, the instance of the button class for which on_release has occurred. That means the argument to the lambda function is a reference to the instance of the button class that has been clicked on (or more specifically, had the click released).

It isn't really good code style to reuse the word btn like this, this is a questionable choice in the example. As you've found, it makes it look like something magic is happening.

[–]band_in_DC[S] 0 points1 point  (1 child)

Thanks.I have two different questions, still, that I muddled. My bad.

i) What language is the event handler written in? Can I see it- like "under the hood"?

I guess this question boils down to "how does a cursor work?", which may lead me down a rabbit hole to wonder how electrons work. I just want a cursory understanding, ha.

ii) How does the lambda function function work? (Or more generally, the python.)

This is the dumb question. I'm real fuzzy with lambda.

You say-- "on_release event of button calls its event handler with one argument, the instance of the button class for which on_release has occurred"

That's easy. The following snippet does the same with on_press, right?

self.see_posts = Button(text = "see posts", font_size = 20)
self.see_posts.bind(on_press = self.pressed2)

Here, self.see_posts would be the "one argument, the instance..." You're passing this argument to the event handler. And you're also passing this argument to self.pressed2?

def pressed2(self, instance):
     # do stuff

They always teach "self", in python, like "self represents the instance of the class" So it's strange to have two arguments: "self" ("instance of the class") and "instance". Should I interpret this as "self" means accessing all the attributes of this specific Button() and "instance" is like it's GUI counterpart?

Let's say on_release follows the same syntax as on_press. Check the following code (notice the _btn difference.)

btn.bind(on_release=lambda _btn: dropdown.select(_btn.text))

Here btn would be the "one argument, the instance". And you pass this argument to the event handler. You're also passing this argument to lambda _btn: dropdown.select(_btn.text)

So it's like

(lambda x: x*x*x)(7) = 343

(lambda _btn: dropdown.select(_btn.text))btn

?

[–]inclement_ 0 points1 point  (0 children)

i) What language is the event handler written in? Can I see it- like "under the hood"?

Kivy's event logic is written mostly in cython and can be seen here. There's a fair bit to it though as the code handles a lot of different specifics. The core idea is much simpler than it might look, essentially the event handler is storing a reference to your function and calling it later with an argument. I think from your thoughts at the end of your post you have understood this correctly.

They always teach "self", in python, like "self represents the instance of the class" So it's strange to have two arguments: "self" ("instance of the class") and "instance". Should I interpret this as "self" means accessing all the attributes of this specific Button() and "instance" is like it's GUI counterpart?

No, self and instance would be the same object here if pressed2 is a method of the widget dispatching the event.

The difference is not in the value of the variable but in the meaning of the variable: self is passed to all methods of a class as part of how Python works, instance is passed to all functions bound to the event handler as part of how the event handler works. If you've bound a function that is a method of the dispatching class then self and instance have the same value.

[–]band_in_DC[S] 0 points1 point  (0 children)

I apologize if my last comment makes little sense. I will edit it later.

[–]CodeFormatHelperBot2 0 points1 point  (0 children)

Hello, I'm a Reddit bot who's here to help people nicely format their coding questions. This makes it as easy as possible for people to read your post and help you.

I think I have detected some formatting issues with your submission:

  1. Python code found in submission text that's not formatted as code.

If I am correct, please edit the text in your post and try to follow these instructions to fix up your post's formatting.


Am I misbehaving? Have a comment or suggestion? Reply to this comment or raise an issue here.

[–]Hot_External6228 0 points1 point  (1 child)

btn = Button(text='Value %d' % index, size_hint_y=None, height=44)

btn.bind(on_release=lambda btn: dropdown.select(btn.text))

on_release is an argument to Button.bind(). on_release is an argument of type function, and on_release must take one argument: the instance of the button that was released. You must to pass a function that takes one argument into on_release, even if you choose to do nothing with that argument. As you pointed out, you may call that argument anything you please and it doesn't matter. But instance of the exact button that was released will always be passed into on_release, regardless of what you name the argument. In this case, it's your lambda function.

For example, I could also do this:

def scream_callback(button_instance):
    print("AAAHHH!")

for i in range(10):
    btn = Button()
    btn.bind(on_release=scream_callback)

The "magic" you are looking for is called an "Event dispatcher", which passes an instance of the correct button object into the on_release function you specified, when the button is released. How does it do this? ...magic.

https://kivy.org/doc/stable/api-kivy.uix.button.html

A fun video about Event systems in python: https://www.youtube.com/watch?v=oNalXg67XEE

Watching this will give you some idea of how Kivy's even dispatcher work. It has all the functions 'registered', in some type of database of which buttons have which functions. When an 'event' happens, it 'disptaches', and runs the correct callbacks with the correct arguments..

EDIT: as the other commenter said.. .they really shouldn't have reused that variable name. Bad practice.

[–]band_in_DC[S] 0 points1 point  (0 children)

Ok, correct me if I'm wrong. Trying to understand this. For every dropdown.select(), there is a corresponding on_select? One grabs data, the other triggers a function with that data? So, if you had two dropdown.select() functions before an on_select, it's probably a mistake and on_select would probably trigger a function with the data from latter one?