decorator and API
Aaron "Castironpi" Brady
castironpi at gmail.com
Wed Sep 17 19:45:40 EDT 2008
On Sep 17, 6:09 pm, "Aaron \"Castironpi\" Brady"
<castiro... at gmail.com> wrote:
> On Sep 17, 4:56 pm, Lee Harr <miss... at hotmail.com> wrote:
>
>
>
> > I have a class with certain methods from which I want to select
> > one at random, with weighting.
(snip)
>
> > The problem I have now is that if I subclass A and want to
> > change the weighting of one of the methods, I am not sure
> > how to do that.
>
> > One idea I had was to override the method using the new
> > weight in the decorator, and then call the original method:
>
> > class B(A):
> > @weight(50)
> > def action_1(self):
> > A.action_1(self)
>
> > That works, but it feels messy.
>
> > Another idea was to store the weightings as a dictionary
> > on each instance, but I could not see how to update that
> > from a decorator.
>
> > I like the idea of having the weights in a dictionary, so I
> > am looking for a better API, or a way to re-weight the
> > methods using a decorator.
>
> > Any suggestions appreciated.
>
> class A:
> weights= WeightOb() #just a dictionary, mostly
> @weights( 10 ) ...
> @weights( 20 ) ...
>
> class B( A ):
> weights= WeightOb( A.weights ) #new, refs "super-member"
> @weights( 50 ) ...
Lee,
Probably overkill. Here's a solution like above.
class WeightOb( object ):
def __init__( self, *supers ):
self.weights= {}
self.supers= supers
def set( self, weight ):
def __callset__( fun ):
self.weights[ fun.func_name ]= weight
return fun
return __callset__
def reset( self, weight, fun ):
self.weights[ fun.func_name ]= weight
return fun
#search parent 'weight' objects
#return 'child-most' weight of 'name'
def get_weight( self, name ):
if name in self.weights:
return self.weights[ name ]
else:
for x in self.supers:
try:
return x.get_weight( name )
except KeyError: #not found
pass
raise KeyError
#returns a dictionary mapping bound instances to weights
#(hence the second parameter)
def contents( self, inst ):
d= {}
for x in reversed( self.supers ):
d.update( x.contents( inst ) )
d.update( dict( [
( getattr( inst, k ), v ) for k, v in self.weights.iteritems( ) ] ) )
return d
class A( object ):
weights= WeightOb( )
@weights.set( 10 )
def action_1( self ):
print 'action_1'
@weights.set( 20 )
def action_2( self ):
print 'action_2'
#WeightOb.contents needs to know which instance to bind
#functions to. Get weights from an instance that has them.
def getweights( self ):
return self.weights.contents( self )
class B( A ):
weights= WeightOb( A.weights )
action_2= weights.reset( 50, A.action_2 )
a= A()
b= B()
print a.weights.get_weight( 'action_1' )
print a.weights.get_weight( 'action_2' )
print b.weights.get_weight( 'action_1' )
print b.weights.get_weight( 'action_2' )
print a.getweights( )
print b.getweights( )
/Output:
10
20
10
50
{<bound method A.action_2 of <__main__.A object at 0x00A04070>>: 20,
<bound meth
od A.action_1 of <__main__.A object at 0x00A04070>>: 10}
{<bound method B.action_2 of <__main__.B object at 0x00A04090>>: 50,
<bound meth
od B.action_1 of <__main__.B object at 0x00A04090>>: 10}
More information about the Python-list
mailing list