is decorator the right thing to use?

Aaron "Castironpi" Brady castironpi at gmail.com
Wed Sep 24 23:33:32 EDT 2008


On Sep 24, 5:21 pm, "Dmitry S. Makovey" <dmi... at athabascau.ca> wrote:
> Hi,
>
> after hearing a lot about decorators and never actually using one I have
> decided to give it a try. My particular usecase is that I have class that
> acts as a proxy to other classes (i.e. passes messages along to those
> classes) however hand-coding this type of class is rather tedious, so I
> decided to use decorator for that. Can somebody tell me if what I'm doing
> is a potential shot-in-the-foot or am I on the right track? (Note, It's
> rather rudimentary proof-of-concept implementation and not the final
> solution I'm about to employ so there are no optimizations or
> signature-preserving code there yet, just the idea).
>
> Here's the code:
>
> class A:
>     b=None
>     def __init__(self,b):
>         self.val='aval'
>         self.b=b
>         b.val='aval'
>
>     def mymethod(self,a):
>         print "A::mymethod, ",a
>
>     def mymethod2(self,a):
>         print "A::another method, ",a
>
> def Aproxy(fn):
>     def delegate(*args,**kw):
>         print "%s::%s" % (args[0].__class__.__name__,fn.__name__)
>         args=list(args)
>         b=getattr(args[0],'b')
>         fnew=getattr(b,fn.__name__)
>         # get rid of original object reference
>         del args[0]
>         fnew(*args,**kw)
>     setattr(A,fn.__name__,delegate)
>     return fn
>
> class B:
>     def __init__(self):
>         self.val='bval'
>
>     @Aproxy
>     def bmethod(self,a):
>         print "B::bmethod"
>         print a, self.val
>
>     @Aproxy
>     def bmethod2(self,a):
>         print "B::bmethod2"
>         print a, self.val
>
> b=B()
> b.bmethod('foo')
> a=A(b)
> b=B()
> b.val='newval'
> a.bmethod('bar')
> a.bmethod2('zam')

It might help to tell us the order of events that you want in your
program.  You're not using 'mymethod' or 'mymethod2', and you probably
want 'return fnew' for the future.  Something dynamic with __getattr__
might work.  Any method call to A, that is an A instance, tries to
look up a method of the same name in the B instance it was initialized
with.

a.foo( ) -> 'in a.foo' -> 'calling b.foo' -> 'return' -> 'return'
a.mymethod( ) -> 'in a.mymethod' -> 'calling b.mymethod' ->
AttributeError: 'b' has no attribute 'mymethod'.



More information about the Python-list mailing list