我一直在关注官方的Kivy PongApp教程(link - 网站底部的整个程序代码),我遇到了一个我无法理解的问题。
我已经定义了移动功能,通过每帧上的速度矢量来改变球的位置。代码:
def move(self):
self.pos = Vector(*self.velocity) + self.pos
然而,当我编写这样的代码时:
def move(self):
self.pos = self.pos + Vector(*self.velocity)
导致错误: ValueError:PongBall.pos值长度是不可变的
为什么,不应该一样吗?
答案 0 :(得分: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))
此外,kivy.properties.ObservableList
子类list
。
不幸的是,kivy.vector.Vector
也是如此,并且任何具有Python经验的人都可以告诉你,list.__add__
连接它的论点。
这意味着通过扩展将向量添加到self.pos
,而不是通过元素添加向量,这会导致self.pos
抱怨,因为它的长度正在发生变化。
它的另一种方式是aronud,因为Vector
overloads __add__
可以进行元素添加。
因为python偏爱__add__
超过__radd__
,所以整个事情都失败了。
答案 1 :(得分:4)
我认为这只是因为Vector类型会覆盖添加以执行向量添加,并且在第一种情况下调用其__add__
,它会自动将self.pos(列表)视为另一个向量。
在第二种情况下,调用self.pos的__add__
,它不知道Vector类型,而是尝试执行扩展列表长度的正常列表添加。这会因您看到的错误而失败,因为pos
必须是固定长度的列表。
总的来说(如果我是对的),问题是+
根据其参数的类型做不同的事情。这通常并不重要,但恰好在这里发挥重要作用。