Kivy官方Pong教程 - Vector的使用(kivy.vector)

chi*_*liq 5 python kivy

我一直在关注官方的Kivy PongApp教程(链接 - 网站底部的整个程序代码),我遇到了一个我无法理解的问题.

我已经定义了移动功能,通过每帧上的速度矢量来改变球的位置.代码:

def move(self):
    self.pos = Vector(*self.velocity) + self.pos
Run Code Online (Sandbox Code Playgroud)

但是,当我编写这样的代码时:

def move(self):
    self.pos = self.pos + Vector(*self.velocity)
Run Code Online (Sandbox Code Playgroud)

它会导致错误:ValueError:PongBall.pos值长度是不可变的

为什么,它不应该是一样的吗?

Joh*_*ree 6

self.pos是一个kivy.properties.ObservableReferenceList.

当您尝试设置此属性时,它会检查以确保新值与旧值的长度相同.

来自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))
Run Code Online (Sandbox Code Playgroud)

另外,kivy.properties.ObservableList子类list.

不幸的是,同样如此kivy.vector.Vector,并且任何具有Python经验的人都可以告诉你,list.__add__连接它的论点.

这意味着向量是self.pos通过扩展它来添加的,而不是通过元素方式添加它,然后self.pos由于其长度在变化而引起抱怨.

它以另一种方式工作,因为Vector 重载是__add__按元素添加的.

因为Python有利于__add____radd__,整个事情失败.


inc*_*ent 5

我认为这只是因为 Vector 类型重写了加法来进行向量加法,并且在第一种情况下__add__调用它,它会自动将 self.pos (列表)视为另一个向量。

在第二种情况下,__add__调用 self.pos ,它不知道 Vector 类型,而是尝试进行正常的列表添加,从而扩展列表的长度。pos由于必须是固定长度的列表,因此失败并出现您看到的错误。

所以总的来说(如果我是对的),问题是+根据参数的类型做不同的事情。这通常并不重要,但在这里却产生了很大的影响。