Neal Becker wrote: > I have an object that expects to call a callable to get a value: > > class obj: > def __init__ (self, gen): > self.gen = gen > def __call__ (self): > return self.gen() As written that looks a bit like
if boolean_expression == True: ... as you could replace inst = obj(callable) with inst = callable but that may be an artifact of the example. > Now I want gen to be a callable that repeats N times. I'm thinking, this > sounds perfect for yield > > class rpt: > def __init__ (self, value, rpt): > self.value = value; self.rpt = rpt > def __call__ (self): > for i in range (self.rpt): > yield self.value > > so I would do: > > my_rpt_obj = obj (rpt ('hello', 5)) > > to repeat 'hello' 5 times (for example). What do you expect to happen when my_rpt_obj is called the sixth time? > But this doesn't work. when obj calls self.gen(), that returns a > generator, not the next value. > > How can I make this work? I can't change the interface of the existing > class obj, which expects a callable to get the next value. >>> class Obj: ... def __init__(self, gen): ... self.gen = iter(gen) ... def __call__(self): ... return next(self.gen) ... >>> class Repeat: ... def __init__(self, value, times): ... self.value = value ... self.times = times ... def __iter__(self): ... for i in range(self.times): ... yield self.value ... >>> r = Obj(Repeat("hello", 3)) >>> r() 'hello' >>> r() 'hello' >>> r() 'hello' >>> r() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __call__ StopIteration Instead of the Repeat class you may use a generator: >>> def repeat(value, times): ... for i in range(times): ... yield value ... >>> r = Obj(repeat("hello", 2)) >>> r() 'hello' >>> r() 'hello' >>> r() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __call__ StopIteration This is for demonstration purposes as there is already itertools.repeat(): >>> import itertools >>> r = Obj(itertools.repeat("world", 2)) >>> r() 'world' >>> r() 'world' >>> r() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __call__ StopIteration Depending on your actual need you may also omit the Obj() class: >>> import functools >>> r = functools.partial(next, itertools.repeat("goodbye", 2)) >>> r() 'goodbye' >>> r() 'goodbye' >>> r() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration Somewhat less formal you can bind the iterator method directly: >>> r = itertools.repeat("GOODBYE", 2).__next__ # next in Python 2 >>> r() 'GOODBYE' >>> r() 'GOODBYE' >>> r() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration -- https://mail.python.org/mailman/listinfo/python-list