[Twisted-Python] "Old style" classes in Twisted and inheritance
Jean-Paul Calderone
exarkun at divmod.com
Tue Nov 13 09:30:44 EST 2007
On Tue, 13 Nov 2007 15:07:21 +0100, Atilla <theatilla at gmail.com> wrote:
>I hope this is the correct place for this question.
>
>I was trying to create a little customized task that sends a (ping)
>message to the clients every X seconds. Because I needed some extra
>bookkeeping, I implemented it as a class instance with a __call__
>method, that is passed to the LoopingCall.
__call__ doesn't have much benefit over a method which a useful name,
for what it's worth. This isn't really related to your question or
problem, though.
>
>However, I also wanted to automatically start the task on init, so I
>thought - it makes a lot of sense to simply Inherit it, call its
>constructor and pass self as the parameter. It was then I realized
>that the classes in twisted are old-style, when my super() call didn't
>work.
Inheritance makes sense for sharing code. It doesn't make sense for
the case you're describing. You could just as easily have your class
create a LoopingCall in its __init__ and start it, rather than making
your class _be_ a LoopingCall.
More generally, some classes in Twisted are classic because they predate
Python's new-style classes. We can't simply change them all to be new-
style now since there are various incompatibilities between classic and
new-style classes.
Speaking of super() specifically, it isn't even correct to use super()
even if you have new-style classes. super() is for cooperative multiple
inheritance: all of the classes in the inheritance hierarchy have to agree
to use it. Even if LoopingCall were new-style, it would also have to
claim that using super() with its __init__ method was supported (actually,
required). And even then there would be no benefit until you also had
multiple inheritance.
>
>Is there any practicular reason for that? Am I wrong to try inherit
>the Looping Call ? Basically my code looks like :
>
>class SillyPinger(object):
> def __init__(self, factory):
> self.factory = factory
> self.pingTargets = {}
>
> pingTask = task.LoopingCall(self)
> pingTask.start(5.0)
>
> def __call__(self):
> # do stuff
> pass
>
The above is good. Do that.
>
>while I'd like to be doing:
>
>class SillyPinger(task.LoopingCall):
> def __init__(self, factory):
> super(SillyPinger, self).__init__(self)
>
> self.factory = factory
> self.pingTargets = {}
>
> self.start(5.0) # get value from .ini here
>
This will always be more fragile, even if you ignore the fact
that super() doesn't work here.
Jean-Paul
More information about the Twisted-Python
mailing list