is decorator the right thing to use?
Aaron "Castironpi" Brady
castironpi at gmail.com
Thu Sep 25 14:50:30 EDT 2008
On Sep 25, 1:22 pm, "Dmitry S. Makovey" <dmi... at athabascau.ca> wrote:
> Aaron "Castironpi" Brady wrote:
> > You should write it like this:
>
> > class B(object):
> > @A.proxy
> > def bmethod(self,a):
>
> > Making 'proxy' a class method on A.
>
> makes sense.
>
> > In case different A instances (do
> > you have more than one BTW?)
>
> yep. I have multiple instances of class A, each one has properties (one per
> class) of classes B, C and D:
>
> class A:
> b=None
> c=None
> d=None
> def __init__(self,b,c,d):
> self.b=b
> self.c=c
> self.d=d
>
> ...magic with proxying methods goes here...
>
> class B:
> def bmethod(self,x): pass # we proxy this method from A
> def bmethod2(self,x): pass # this is not proxied
> class C:
> def cmethod(self,x): pass # we proxy this method from A
> class D:
> def dmethod(self,x): pass # we proxy this method from A
>
> a=A(B(),C(),D())
> x='foo'
> a.bmethod(x)
> a.cmethod(x)
> a.dmethod(x)
> a.bmethod2(x) # raises error as we shouldn't proxy bmethod2
>
> above is the ideal scenario.
>
> > What you've said implies that you only have one B instance, or only
> > one per A instance. Is this correct?
>
> yes. as per above code.
>
> > I agree that __setattr__ is the canonical solution to proxy, but you
> > have stated that you want each proxied method to be a member in the
> > proxy class.
>
> well. kind of. if I can make it transparent to the consumer so that he
> shouldn't do:
>
> a.b.bmethod(x)
>
> but rather:
>
> a.bmethod(x)
>
> As I'm trying to keep b, c and d as private properties and would like to
> filter which calls are allowed to those. Plus proxied methods in either one
> always expect certain parameters like:
>
> class B:
> def bmethod(self,c,x): pass
>
> and A encapsulates 'c' already and can fill in that blank automagically:
>
> class A:
> c=None
> b=None
> def bmethod(self,c,x):
> if not c:
> c=self.c
> b.bmethod(self,c,x)
>
> I kept this part of the problem out of this discussion as I'm pretty sure I
> can fill those in once I figure out the basic problem of auto-population of
> proxy methods since for each class/method those are going to be nearly
> identical. If I can autogenerate those on-the-fly I'm pretty sure I can add
> some extra-logic to them as well including signature change where
> A::bmethod(self,c,x) would become A::bmethod(self,x) etc.
Do you want to couple instances or classes together?
If A always proxies for B, C, and D, then the wrapper solution isn't
bad. If you're going to be doing any instance magic, that can change
the solution a little bit.
There's also a revision of the first implementation of Aproxy you
posted, which could stand alone as you have it, or work as a
classmethod or staticmethod.
> 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
def Aproxy(fn):
def delegate(self,*args,**kw):
print "%s::%s" % (args[0].__class__.__name__,fn.__name__)
fnew=getattr(self.b,fn.__name__)
return fnew(*args,**kw)
setattr(A,fn.__name__,delegate)
return fn
More information about the Python-list
mailing list