Reputation: 1222
I've been following official Kivy PongApp tutorial (link - whole program code at the bottom of site) and I've faced a problem I can't really understand.
I've defined the move function to change the position of the ball by a velocity vector on each frame. The code:
def move(self):
self.pos = Vector(*self.velocity) + self.pos
However, when I've written the code like this:
def move(self):
self.pos = self.pos + Vector(*self.velocity)
It results in an error: ValueError: PongBall.pos value length is immutable
Why, shouldn't it be the same?
Upvotes: 6
Views: 1534
Reputation: 1088
self.pos
is a kivy.properties.ObservableReferenceList
.
When you attempt to set this property it checks to make sure that the new value is the same length as the old value.
From kivy.properties.ReferenceProperty
:
cdef check(self, EventDispatcher obj, value):
cdef PropertyStorage ps = obj.__storage[self._name]
if len(value) != len(ps.properties):
raise ValueError('%s.%s value length is immutable' % (
obj.__class__.__name__, self.name))
In addition, kivy.properties.ObservableList
subclasses list
.
Unfortunately, so does kivy.vector.Vector
, and as anyone with Python experience can tell you, list.__add__
concatenates its arguments.
What this means is that vector is added to self.pos
by extending it, not by adding it elementwise, which then causes self.pos
to complain because its length is changing.
It works the other way aronud because Vector
overloads __add__
to do element-wise addition.
Because python favors __add__
over __radd__
, the whole thing fails.
Upvotes: 7
Reputation: 29488
I think this is just because the Vector type overrides addition to do vector addition, and in the first case its __add__
is called which automatically treats self.pos (a list) as another vector.
In the second case, the __add__
of self.pos is called, which doesn't know about the Vector type and tries instead to do normal list addition which extends the length of the list. This fails with the error you see, since the pos
must be a list of fixed length.
So overall (if I'm right), the problem is that +
does different things depending on the types of its arguments. This usually isn't important, but happens to make a big difference here.
Upvotes: 5