is decorator the right thing to use?
Bruno Desthuilliers
bruno.42.desthuilliers at websiteburo.invalid
Thu Sep 25 04:50:04 EDT 2008
Dmitry S. Makovey a écrit :
> Aaron "Castironpi" Brady wrote:
>
>> 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.
>
> well 'mymethod' and 'mymethod2' were there just to show that A doesn't
> function as a pure proxy - it has methods of it's own. See my respnse to
> Steve - I proxy messages to more than one aggregated object. going over
> them on __getattr__ to look up methods just doesn't seem to be really
> efficient to me (I might be wrong though). Decorators seemed to present
> good opportunity to simplify the code (well except for the decorator
> function itself :) ), make code bit more "fool-proofed" (and give me the
> opportunity to test decorators in real life, he-he).
>
> So decorators inside of B just identify that those methods will be proxied
> by A. On one hand from logical standpoint it's kind of weird to tell class
> that it is going to be proxied by another class,
Indeed - usually, proxied objects shouldn't have to be aware of the
fact. That doesn't mean your variation on the proxy pattern is
necessarily bad design (hard to tell without lot of context anyway...),
but still there's some alarm bell ringing here IMHO - IOW : possibly the
right thing to do, but needs to be double-checked.
> but declaration would be
> real close to original function definition which helps to identify where is
> it used.
>
> Note that my decorator doesn't change original function - it's a subversion
> of decorator to a certain degree as I'm just hooking into python machinery
> to add methods to A upon their declaration in B (or so I think).
I wouldn't call this a "subversion" of decorators - it's even a pretty
common idiom to use decorators to flag some functions/methods for
special use.
Now I'm not sure I really like your implementation. Here's a possible
rewrite using a custom descriptor:
class Proxymaker(object):
def __init__(self, attrname):
self.attrname = attrname
def __get__(self, instance, cls):
def _proxied(fn):
fn_name = fn.__name__
def delegate(inst, *args, **kw):
target = getattr(inst, self.attrname)
#return fn(target, *args,**kw)
method = getattr(target, fn_name)
return method(*args, **kw)
delegate.__name__ = "%s_%s_delegate" % \
(self.attrname, fn_name)
setattr(cls, fn_name, delegate)
return fn
return _proxied
class A(object):
def __init__(self,b):
self.val='aval'
self.b=b
b.val='aval'
proxy2b = Proxymaker('b')
def mymethod(self,a):
print "A::mymethod, ",a
def mymethod2(self,a):
print "A::another method, ",a
class B(object):
def __init__(self):
self.val='bval'
@A.proxy2b
def bmethod(self,a):
print "B::bmethod"
print a, self.val
@A.proxy2b
def bmethod2(self,a):
print "B::bmethod2"
print a, self.val
My point is that:
1/ you shouldn't have to rewrite a decorator function - with basically
the same code - for each possible proxy class / attribute name pair combo
2/ making the decorator an attribute of the proxy class makes
dependencies clearer (well, IMHO at least).
I'm still a bit uneasy wrt/ high coupling between A and B, and if I was
to end up with such a design, I'd probably take some times to be sure
it's really ok.
My cents...
More information about the Python-list
mailing list