[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