chilliq
chilliq

Reputation: 1222

Kivy official Pong tutorial - usage of Vector (kivy.vector)

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

Answers (2)

John Tyree
John Tyree

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

inclement
inclement

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

Related Questions