L
Lee Harr
I have a class with certain methods from which I want to select
one at random, with weighting.
The way I have done it is this ....
import random
def weight(value):
def set_weight(method):
method.weight = value
return method
return set_weight
class A(object):
def actions(self):
'return a list of possible actions'
return [getattr(self, method)
for method in dir(self)
if method.startswith('action_')]
def action(self):
'Select a possible action using weighted choice'
actions = self.actions()
weights = [method.weight for method in actions]
total = sum(weights)
choice = random.randrange(total)
while choice> weights[0]:
choice -= weights[0]
weights.pop(0)
actions.pop(0)
return actions[0]
@weight(10)
def action_1(self):
print "A.action_1"
@weight(20)
def action_2(self):
print "A.action_2"
a = A()
a.action()()
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.
_________________________________________________________________
Explore the seven wonders of the world
http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE
one at random, with weighting.
The way I have done it is this ....
import random
def weight(value):
def set_weight(method):
method.weight = value
return method
return set_weight
class A(object):
def actions(self):
'return a list of possible actions'
return [getattr(self, method)
for method in dir(self)
if method.startswith('action_')]
def action(self):
'Select a possible action using weighted choice'
actions = self.actions()
weights = [method.weight for method in actions]
total = sum(weights)
choice = random.randrange(total)
while choice> weights[0]:
choice -= weights[0]
weights.pop(0)
actions.pop(0)
return actions[0]
@weight(10)
def action_1(self):
print "A.action_1"
@weight(20)
def action_2(self):
print "A.action_2"
a = A()
a.action()()
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.
_________________________________________________________________
Explore the seven wonders of the world
http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE