generator object or 'send' method?
Aaron Brady
castironpi at gmail.com
Wed Feb 11 18:17:11 CET 2009
On Feb 11, 4:41 am, greg <g... at cosc.canterbury.ac.nz> wrote:
> Aaron Brady wrote:
> > It would receive the 'send' from a different point in control
> > flow than its usual 'next'. Should it repeat a value if it receives a
> > 'send'?
>
> No. This requirement clearly indicates that send() is
> the wrong tool for the job.
>
> I would use a class with a generator as a method, e.g.
>
> class Multiples:
>
> m = 1
>
> def set_multiplier(self, m):
> self.m = m
>
> def generate(self, limit):
> for i in xrange(limit):
> yield i * self.m
>
> g = Multiples()
> for x in g.generate(10):
> print x
> if x == 3:
> g.set_multiplier(42)
>
> produces
>
> 0
> 1
> 2
> 3
> 168
> 210
> 252
> 294
> 336
> 378
>
> --
> Greg
Alright, but you don't have to go so far as to create an entire
class. It's alright to use a formula. Here's a way to add a
dictionary to a generator instance.
def gen_dict( fun ):
def inner( *ar, **kw ):
self.gen= fun( self, *ar, **kw )
return self
class GenWrapper:
def __iter__( self ): return self
def __next__( self, *ar, **kw ): return self.gen.__next__
( *ar, **kw )
self= GenWrapper()
return inner
It's a shame that you can't set 'self.__next__= self.gen.__next__'.
It costs an entire level of call depth. On the other hand, I'm not
sure a pure delegate class is possible.
The decorator just puts the generator object in a 'gen' attribute, and
adds itself to the '__init__' argument list. So the generator has a
'self' argument, which is of type 'instance', and allows dynamic
attributes.
@gen_dict
def jumper( self, N= 1, K= 1 ):
self.N, self.K= N, K
while 1:
yield self.N
self.N+= self.K
j= jumper()
print( next( j ) )
j.K= 4
print( next( j ) )
It might need some touch-ups to run in Python 2. Neat mix. It's a
cool hybrid between Terry's and Greg's idea, and a bare generator.
Unfortunately, if you want 'self' to have any methods, you'll probably
need a class... though maybe it could inherit from 'GenWrapper'. What
do you think?
P.S. Here's a slightly simpler version.
def gen_dict( fun ):
class GenWrapper:
def __init__( self, *ar, **kw ):
self.gen= fun( self, *ar, **kw )
def __iter__( self ): return self
def __next__( self, *ar, **kw ): return self.gen.__next__
( *ar, **kw )
return GenWrapper
P.P.S. Simpler, but a line longer.
class GenWrapper:
def __init__( self, fun ):
self.fun= fun
def __call__( self, *ar, **kw ):
self.gen= self.fun( self, *ar, **kw )
return self
def __iter__( self ): return self
def __next__( self, *ar, **kw ): return self.gen.__next__( *ar,
**kw )
More information about the Python-list
mailing list