functors
Jack Diederich
jack at performancedrivers.com
Wed Jul 2 03:22:17 EDT 2003
On Tue, Jul 01, 2003 at 06:25:18PM -0700, Tom Plunket wrote:
> How can I create a functor object in Python?
>
> What I want (being a C++ coder <g>), is to be able to create an
> object that I is callable. The following is my attempt, but it
> doesn't work:
I would make countdown dumber, and make the call more explicit
def countdown(thismany)
for (i) in range(thismany):
yield False
yield True
while True:
yield False
> def Update(self):
> while not self.done:
> self.countdown.Update()
becomes
def Update(self):
while not self.done:
if (self.countdown.next()):
self.Callback() # person reading the code knows what happens
but if you really want the hidden callback, just change the countdown()
def countdown(thismany, call_this):
for (i) in range(thismany):
yield 69 # ignored by caller anyway
call_this() # make the callback
while True:
yield 42 # more ignored yields
But I'm not sure if this is what you really want, the countdown() keeps going
even after it has fired. Hence the 'While True: yield False'
If you need the callback because you have a whole bunch and can't keep track
of each one individually, I'd make a parent class that decrements everyone
and pops people after they fire.
class Watcher(object):
def __init__(self):
self.watched = []
self.i = 0
def watch(count, call_this):
self.watched.append((self.i+count, call_this))
def decrement(self):
self.i += 1
callthese = filter(lambda x:x[0]<i, self.watched)
self.watched = filter(lambda x:x[0]>=i, self.watched)
for (dummy, callthis) in callthese:
callthis()
Just for fun, let's play with itertools
from itertools import *
def countdown(thismany):
return chain(repeat(False, thismany), [True], repeat(False))
or the abusive
def countdown(thismany, callthis):
def fakeout(): # because "lambda x:yield x()" isn't legal
yield callthis()
return chain(repeat(None, thismany-1), fakeout(), repeat(None))
and the totally abusive (and totally untested)
class Watcher(object):
def __init__(self):
self.watched = repeat(None)
self.curr = 0
def watch(self, count, callthis):
def fakeout():
yield callthis()
assert(count > self.curr) # new job must fire after the current longest one
self.watched = chain(repeat(None, count-1-self.curr), fakeout(), self.watched)
self.curr = count
def decrement(self):
if (self.curr):
self.curr -= 1
self.watched.next()
Enjoy,
-jackdied
More information about the Python-list
mailing list