About data binding with custom components

I created the property in the custom component dialog and it was working with the exception of the write back. Then I created the getter and the setter and… what happened to the property previously created?

Custom properties, just like data bindings, are just a shorthand for standard Python assignment. If you have a custom property called foo, then init_components() will do this on startup:

self.foo = <value from designer>

If you don’t do anything else, that just sets a normal attribute on your object called foo. I’m sure you do this all the time.

But if you use @property, you’re making a descriptor that handles the foo attribute. This is a standard Python feature: now, whenever you read or write self.foo, you actually call those getter and setter functions. This is very helpful, because it lets you do things (like update the UI) whenever you read or write that attribute.


Fun digression:

Ever wondered why self.my_func(x) gets translated to def my_func(self, x)? Where does that extra argument come from? It’s because Python functions work as descriptors!

Getting self.my_func actually invokes the descriptor, which generates a shim function that adds the self value to its arguments before calling the original function. So if you do method = self.my_func, and call then method(x), it works. method is a shim function - it takes one argument, and knows what self is.

Descriptors are one of my favourite parts of Python. If you want to learn more about them, you can start here.

2 Likes