Table of Contents
This is a continuation of Learning Kivy - Part 4.
As noted in Part 4 for Pong.py and pong.kv, we've come across an important type in the Player class, of NumericProperty, the instance of which is assigned to player1 class variable.
With respect to this program, it is an important part of being able to dynamically update the Label's text with the changing score.
Looking at kivy.org site to get some insight into the NumericProperty, I noticed the following:
Theses properties implement the Observer pattern. They help you to:
- Easily manipulate widgets defined in the Kv language
- Automatically observe any changes and dispatch functions/code accordingly
- Check and validate values
- Optimize memory management
I know from previous experience what an Observer pattern is, but in essence, it allows one part of code to inform other interested parts of code that something has changed - the change is an event, and those parties that have registered their interest through a callback function, are informed of this change. Here's a more detailed explanation from Wikipedia: Observer Pattern
It appears that, by setting the class PongGame's attribute player1 to an instance Player, and Player is of type Widget, and Player has an attribute of score which is of type NumericProperty, we are making use of the Observer Pattern via the NumericProperty, which will(from kivy.org) "...automatically observe any changes and dispatch functions/code accordingly". So that appears to be the magic that let's us change.
In other words, I'm thinking it means: when we update the 'score' attribute, since it's of type NumericProperty, then it gets updated in the pong.kv class
Recommended additional info
Here's a good question/answer thread on Kivy NumericProperty. Here's a clip from it.
[Alexandar Taylor]: Properties hook into kivy's event system to reference each other in automatically updated ways, dispatch events when changed etc. In comparison, a normal python class level property...doesn't. Kivy properties also take care of class uniqueness, whereas class attributes are shared by all class instances which can cause you unexpected problems if they're mutable.The guy that wrote the above, Alexander Taylor, also has a series of youtube casts. Here's one dealing with this issue.
For the ReferenceListProperty, this creates a property that looks like a list, but whose elements when accessed or changed automatically reference or change the component velocity_x or velocity_y. In comparison, your example of just using a tuple does none of that - if you access velocity you'll probably not even get a number but instead the NumericProperty object you defined it to point at. In contrast, the ReferenceListProperty acesses and returns the velocity_x property.
Same goes for the NumericProperty. You could create class level python attributes if you wanted (or, more usefullly, standard instance attributes created in __init__), but then you can't bind to their changes etc. with kivy's event system. Learning more about kivy will make it clear how it ties together, you generally always will be thinking in terms of properties affecting each other via the bindings that kivy properties allow.