deferred decorator

B

Bryan

i was intrigued with a recently posted cookbook recipe which implements deferred
results with decorators:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/355651

the problem i see with this recipe is that the author only tested his code by
printing the values which causes __getattr__ to be called with '__str__' and
work correctly. but, if you were to remove the print statements and just do a v
+ v, __getattr__ won't get called as he expected and the join will never happen.
i think by making __coerce__ as smart as __getattr__ this recipe would work.
can someone validate that i'm correct in what i'm saying?

i'm also curious if it's possible to write this recipe using the new class style
for the Deffered class. it appears you can nolonger delegate all attributes
including special methods to the contained object by using the __getattr__ or
the new __getattribute__ methods. does anyone know how to port this recipe to
the new class style?

thanks,

bryan
 
N

Nick Coghlan

Bryan said:
i'm also curious if it's possible to write this recipe using the new
class style for the Deffered class. it appears you can nolonger
delegate all attributes including special methods to the contained
object by using the __getattr__ or the new __getattribute__ methods.
does anyone know how to port this recipe to the new class style?

Override __getattribute__. I don't know why you think it doesn't let you
override all attribute accesses, as that's exactly what it is for.

Cheers,
Nick.
 
B

Bryan

Nick said:
Override __getattribute__. I don't know why you think it doesn't let you
override all attribute accesses, as that's exactly what it is for.

Cheers,
Nick.

here's an example. __getattribute__ gets called for x but not for the special
method __add__. and the __str__ method was found in the base class object which
printed the memory location, but didn't call __getattribute__. so
__getattribute__ cannot be used to capture special methods and delegate them to
an encapsulated object. this is why i'm asking what the technique using new
classes would be for this recipe.

.... def __getattribute__(self, name):
.... raise AttributeError('__getattribute__ is called')
....Traceback (most recent call last):
File "<interactive input>", line 1, in ?
Traceback (most recent call last):
'<__main__.Foo object at 0x0118AD10>'
 
N

Nick Coghlan

Bryan said:
here's an example. __getattribute__ gets called for x but not for the
special method __add__. and the __str__ method was found in the base
class object which printed the memory location, but didn't call
__getattribute__. so __getattribute__ cannot be used to capture special
methods and delegate them to an encapsulated object. this is why i'm
asking what the technique using new classes would be for this recipe.

Hmm, good point. I now have a vague idea why it happens that way, too
(essentially, it appears the setting of the magic methods causes the interpreter
to be notified that the object has a Python-defined method to call. With only
__getattribute__ defined, that notification doesn't happen for all of the other
magic methods).

This actually makes sense - otherwise how would the method which implements
__getattribute__ be retrieved?

Similarly, in the existing recipe, none of __init__, __call__, __coerce__ or
__getattr__ are delegated - the behaviour is actually consistent for all magic
methods (I'm curious how the existing recipe actually works - it seems the use
of "self.runfunc" in __call__ should get delegated. It obviously isn't, though).

Something like the following might work (I haven't tested it though):

class Deferred(object):
...

def lookup_magic(f_name):
def new_f(self, *args, **kwargs):
return getattr(self, f_name)(*args, **kwargs)
return new_f

func_list = ['__add__', '__radd__', ...]
for f_name in func_list:
setattr(Deferred, f_name) = lookup_magic(f_name)

A metaclass may actually provide a cleaner solution, but I'm not quite sure
where to start with that.

Cheers,
Nick.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top