我想继承pyglet.clock模块的Clock类,但是当我使用schedule_interval时遇到了一些麻烦:
以下代码不会打印任何内容,如果没有打勾,则对象c看起来像是:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
class Test(object):
def update(self, dt):
print dt
w = pyglet.window.Window()
@w.event
def on_draw():
w.clear()
t = Test()
c = pyglet.clock.Clock()
c.schedule_interval(t.update, 1/60.0)
pyglet.app.run()
但接下来的工作正常。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
pyglet.clock.set_default(self)
class Test(object):
def update(self, dt):
print dt
w = pyglet.window.Window()
@w.event
def on_draw():
w.clear()
t = Test()
c = Clock()
c.schedule_interval(t.update, 1/60.0)
pyglet.app.run()
唯一的区别是Clock的构造函数方法中的pyglet.clock.set_default(self)句子。
我认为这不清楚,或者至少不是将pyglet.clock.Clock子类化为拥有自己派生的Clock类的最佳方法。
问题:
有一些方法可以使用Pyglet自动设置默认时钟吗?
有更优雅或pythonic的解决方案吗?
可以在没有pyglet.clock.set_default(self)行的情况下执行此操作吗?
答案 0 :(得分:1)
我没有使用pyglet,但这是我的猜测:
你快到了。你的第一次实现可能不起作用的原因是因为这些行:
c = pyglet.clock.Clock()
c.schedule_interval(t.update, 1/60.0)
在这里,您正在创建一个新的Clock实例,并在其上安排回调。但是,您实际上并没有将该时钟实例与pyglet相关联。所以,当你跑...
pyglet.app.run()
...你从未真正告诉pyglet有关新的时钟实例c
。相反,pyglet将使用它自己创建的实例。看看这个source code for pyglet from the clock module ...:
# Default clock.
_default = Clock()
def set_default(default):
'''Set the default clock to use for all module-level functions.
By default an instance of `Clock` is used.
:Parameters:
`default` : `Clock`
The default clock to use.
'''
global _default
_default = default
def get_default():
'''Return the `Clock` instance that is used by all module-level
clock functions.
:rtype: `Clock`
:return: The default clock.
当pyglet启动时,它会创建自己的时钟实例(称为_default
)。如果您想使用自己的,则需要使用set_default()
来替换它。因此,要修复第一段代码,您可能需要执行以下操作之一:
c = pyglet.clock.get_default()
c.schedule_interval(t.update, 1/60.0)
...或...
c = pyglet.clock.Clock()
pyglet.clock.set_default(c)
c.schedule_interval(t.update, 1/60.0)
上面的第二个例子是没有意义的:pyglet已经为你提供了一个Clock的实例,所以你真的只是复制了pyglet已经为你做过的事情。无论哪种方式,你最终都会在pyglet使用的时钟上安排回调。
所以,现在应该有意义的是,你确实需要致电set_default()
。这就是你告诉pyglet使用你的对象而不是默认使用它的方法。现在,您可以可以想象将此set_default()
调用放在您当前拥有它的位置(在构造函数中)。但是,这样做可能更有意义......
class Clock(pyglet.clock.Clock):
def __init__(self):
super(Clock, self).__init__()
...
c = Clock()
pyglet.clock.set_default(c)
修改强>:
回答你为什么要在构造函数之外执行此操作的问题:
首先,作为一般经验法则,构造函数只应用于构造对象。通过添加set_default,您不仅可以构建对象,还可以更改其他实体(pyglet.clock模块)的状态。这可能会引起混淆,我将在下面展示。假设我编写的代码看起来像这样......
c = MyClock()
c2 = UnpausedClock()
在此示例中,我之前已实现了两种不同的时钟类型:NewClock
和UnpausedClock
。游戏取消暂停时,UnpausedClock
只会考虑时间过去。如果我将set_default()
放在这两个新类的构造函数中,那么UnpausedClock
将成为新的默认时钟(我不想要)。不要将set_default()
放在构造函数中,而是执行以下操作:
c = MyClock()
c2 = UnpausedClock()
pyglet.clock.set_default(c)
我的代码更明确,更少混淆。
当然,代码将以任何一种方式工作,但我觉得使用set_default OUTSIDE构造函数可以让您在以后需要时更灵活地使用该类。