Re: [Twisted-Python] A Python metaclass for Twisted allowing __init__ to return a Deferred
Hi JP
I usually solve this kind of problem like this:
d = aFuncReturningADeferred() d.addCallback(MyClass) d.addCallback(cb)
See? I knew there'd be a 3-line solution somewhere :-) That's very cute, I'd never have thought of that... Python is so nice. My (weak?) response is that your solution isn't quite so general. What if I want __init__ to generate the deferred based on its args, or on the result of other functions called based on its args? Yes, I can do all that work before using your lovely d.addCallback(MyClass), but then the logic of what the class does is starting to leak out into the code that should be calling the class. And you can't encapsulate THAT code into another class, because its __init__ would in turn have to return a deferred. BTW, I sometimes have the feeling that Deferreds are like how M$ characterizes the GPL. Viral. Once you call anything creating a Deferred, you're hooked - whatcha gonna do with that Deferred boy? Take one sip of the Deferred Kool Aid and the next thing you know you're on a drip.
I'll not try to claim anything about the level of elegance, though. :)
History will smile on you JP.
For less surprisiness, I'd suggest that you at least restrict the result of the Deferred returned from __init__ to firing with None or self and make the argument to the first callback on the Deferred returned by MyClass() just be the new instance.
Hmmm. OK. I think you're right. The caller has no business knowing what the Deferred returned in any case. And if the class itself wants the result it can add a callback and stick it on self. That's good, I had been hoping to return just the instance, but then it occurred to me to send back the result too. BTW, I started out trying to think of a way to just say x = MyClass(...) and have that result in the instance. But the only ways I could think of doing that were disgusting and broken (e.g., make a *function* called MyClass and use inlineCallbacks and some other class the metaclass would build). So the __instantiate__ call seemed like a big win, even though I don't like it much either. Thanks! Terry
* Terry Jones <terry@jon.es> [2008-11-03 01:16:50 +0100]:
I usually solve this kind of problem like this:
d = aFuncReturningADeferred() d.addCallback(MyClass) d.addCallback(cb)
See? I knew there'd be a 3-line solution somewhere :-)
That's very cute, I'd never have thought of that... Python is so nice.
My (weak?) response is that your solution isn't quite so general. What if I want __init__ to generate the deferred based on its args, or on the result of other functions called based on its args? Yes, I can do all that work before using your lovely d.addCallback(MyClass), but then the logic of what the class does is starting to leak out into the code that should be calling the class. And you can't encapsulate THAT code into another class, because its __init__ would in turn have to return a deferred.
You can, however, encapsulate it into a classmethod or free function that you call to get an instance of MyClass. This is a pattern often seen when there are various ways to build an instance of some class; you'll have a very basic __init__, and then a bunch of factory functions or classmethods that do more complicated work before passing the results in to the class's constructor.
BTW, I sometimes have the feeling that Deferreds are like how M$ characterizes the GPL. Viral. Once you call anything creating a Deferred, you're hooked - whatcha gonna do with that Deferred boy? Take one sip of the Deferred Kool Aid and the next thing you know you're on a drip.
Just wait until you start trying to combine iterators and deferreds ;) -- mithrandi, i Ainil en-Balandor, a faer Ambar
participants (2)
-
Terry Jones -
Tristan Seligmann