I have a Clock class who inherites from pyglet.clock.Clock and behaves like a Singleton.
Into the constructor method I have the following line:
pyglet.clock.set_default(self)
Who changes the state of the default clock of pyglet, setting my Clock object as the default clock.
The constructor method leaves the Clock object into a valid state (without this line in the constructor the clock don't tick!).
Changing another entity state in the constructor:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
import singleton
class Clock(pyglet.clock.Clock):
__metaclass__ = singleton.Singleton
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()
On the other hand I can do:
Calling pyglet.clock.set_default outside of the constructor:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyglet
import singleton
class Clock(pyglet.clock.Clock):
__metaclass__ = singleton.Singleton
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 = Clock()
pyglet.clock.set_default(self)
c.schedule_interval(t.update, 1/60.0)
pyglet.app.run()
In this case the call:
pyglet.clock.set_default(self)
Is outside of the constructor method and then the constructor method don't change the state of another entity.
The questions:
What is the solution more elegant or pythonic?
Is any of these solutions a best practice?
How do you resolve this issue?
-
\$\begingroup\$ Why are you subclassing pyglet's Clock? \$\endgroup\$Winston Ewert– Winston Ewert2013年05月04日 02:52:56 +00:00Commented May 4, 2013 at 2:52
-
\$\begingroup\$ @WinstonEwert I want to let the code more clean if I have to add more functionality to the class in the future and let only the more primitive objects modules interacts with the pyglet library. \$\endgroup\$Super User– Super User2013年05月04日 03:01:17 +00:00Commented May 4, 2013 at 3:01
2 Answers 2
In Python, a singleton should be a module, not a class. There's no good reason to define a class for that. That's what's going on in pyglet's case with pyglet.clock
. If you want to define your own version you should do something like:
# myclock.py
from pyglet.clock import *
Then you can add functions/etc to that module to get additional behavior. This way you don't even need to call the set_default function.
-
\$\begingroup\$ I think it is a design question. Because without a metaclass Singleton you can call the Clock class and create another Clock instance. \$\endgroup\$Super User– Super User2013年05月04日 19:51:52 +00:00Commented May 4, 2013 at 19:51
-
\$\begingroup\$ @SuperUser, sure, you could design it so that you could create many Clock instances. I'd be all in favor of that. But that's not what you did. \$\endgroup\$Winston Ewert– Winston Ewert2013年05月04日 19:55:20 +00:00Commented May 4, 2013 at 19:55
-
\$\begingroup\$ Yes, but I point that with your proposed solution: A subclass Clock (without a Singleton restriction) and a variable module clock you are still having a non-Singleton object. \$\endgroup\$Super User– Super User2013年05月04日 20:00:15 +00:00Commented May 4, 2013 at 20:00
-
\$\begingroup\$ @SuperUser, I'm confused. What do you think my proposed solution is? \$\endgroup\$Winston Ewert– Winston Ewert2013年05月04日 20:02:11 +00:00Commented May 4, 2013 at 20:02
-
\$\begingroup\$ You proposed the pyglet approach, but if I do from pyglet.clock import * I still can call Clock() and create another Clock instance. \$\endgroup\$Super User– Super User2013年05月04日 20:05:24 +00:00Commented May 4, 2013 at 20:05
While I agree with @WinstonEwert on usage of singletons in Python (having module singletons is Pythonic because their code is executed only once per program run, and modules can be imported from other modules which should have access to this singleton), if the program is simple and will not be expanded upon, I would go with your second version, which can be fixed in a much simpler way by replacing
pyglet.clock.set_default(self)
with
pyglet.clock.set_default(c)
self
is (by convention) the first argument of every bound method that represents the object on which this method was called, thus the calling expression has no meaning outside of your class and should fail (because self
should be undefined at that point). To point to your constructed object of class Class
you may use the name you bound it to, that is, c
.
Explore related questions
See similar questions with these tags.