Re: [Twisted-Python] A Python metaclass for Twisted allowing __init__ to return a Deferred
"Esteve" == Esteve Fernandez <esteve@sindominio.net> writes: Esteve> Alternatively a function would suffice: [snip] Esteve> def FooFactory(value): Esteve> return aFuncReturningADeferred(value).addCallback(SimpleFoo)
Right. That's JP's solution (though he didn't bother wrapping it in a func): pass the result of the Deferred to the constructor of the class. But I like your __new__ approach better, as it puts the logic for creating deferreds, adding callbacks to them, doing other stuff etc., into the class itself. It's in __new__ instead of __init__, but that seems perfect to me. My approach, like all of them (and necessarily so) was two-phase, but my second phase required the calling of __instantiate__. By using __new__ and __init__ instead of my __init__ and __instantiate__, you moved the phases back and just hitch-hike on Python's existing machinery. That's why I like that approach, plus, as I keep saying, it keeps the Deferred logic inside the class where it belongs. T
On 02:20 pm, terry@jon.es wrote:
But I like your __new__ approach better, as it puts the logic for creating deferreds, adding callbacks to them, doing other stuff etc., into the class itself. It's in __new__ instead of __init__, but that seems perfect to me.
In my humble (but correct) opinion, this is actually a lot worse than using __init__ :). I'd like to discourage you from using it. Using __new__ like this is violating its implicit metaprogramming contract within Python. __new__ is really supposed to be about allocation; it means, give me an uninitialized instance of this thing (which I will then initialize using __init__). It is best used to implement things like token interning or free lists for small value objects. Keeping __new__ doing what it's supposed to is important to libraries which use introspection. Serialization libraries, twisted.spread.jelly being an obvious example, may need to use __new__ as an API in order to create cyclic relationships. Consider the output of this program: class Something(object): def __new__(cls, *a, **k): self = object.__new__(cls, *a, **k) oself = SomethingElse(self) return oself class SomethingElse(object): def __init__(self, sth): self.sth = sth from twisted.spread.jelly import jelly, unjelly print unjelly(jelly(Something())).sth Using __new__ is functionally equivalent to defining a classmethod, as I suggested, but rather than using the "classmethod" decorator it relies on implicitly hacking into bits of the Python object model. Explicit is better ... well, you know the rest :).
participants (2)
-
glyph@divmod.com -
Terry Jones