【发布时间】:2016-04-27 20:58:23
【问题描述】:
我正在开发一款使用 Kivy 的游戏,玩家可以通过按键来发射炸弹。这是一个简化的函数:
def shoot(self, world):
# self is the player widget
bomb = Bomb(pos=self.pos)
world.add_entity(bomb)
有趣的是,当玩家射击时,无论他走到哪里,炸弹都会跟着他移动。
调试后我意识到这是因为播放器和炸弹共享velocity 属性。
Player 类和Bomb 类都继承了Entity,它在类级别定义了velocity = ObjectProperty(Vector(0, 0))。运行时调试显示这两个对象引用了完全相同的对象。
问题是,Kivy 属性实际上应该在每个实例上创建单独的属性。那么为什么会出现这种不需要的共享状态,我该如何解决呢?
解决方案
感谢@Tshirtman 对this question 答案的评论,我找到了问题和解决方案。
事实证明 Kivy 属性有一个陷阱,实例化它们时设置的初始值将由类的所有实例共享。
澄清一下:
# this implementation results in the property shared by all instances
class MyWidget(Widget):
my_field = ObjectProperty(MyObject())
w1 = MyWidget()
w2 = MyWidget()
w1.my_field is w2.my_field # True
如您所见,my_field 实际上是在两个实例之间共享的。
为避免这种行为,除了设置类级属性外,请确保在特定对象上设置属性。
例如:
class MyWidget(Widget):
my_field = ObjectProperty()
def __init__(self, **kwargs):
super(MyWidget, self).__init__(**kwargs)
self.my_field = MyObject() # explicitly set the value on the object
w1 = MyWidget()
w2 = MyWidget()
w1.my_field is w2.my_field # False
当显式设置字段的值时,该字段不会在实例之间共享。希望这对某人有所帮助。
【问题讨论】: