Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #85210 > unrolled thread

basic generator question

Started byNeal Becker <ndbecker2@gmail.com>
First post2015-02-04 08:23 -0500
Last post2015-02-05 03:09 +1100
Articles 2 — 2 participants

Back to article view | Back to comp.lang.python


Contents

  basic generator question Neal Becker <ndbecker2@gmail.com> - 2015-02-04 08:23 -0500
    Re: basic generator question Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-05 03:09 +1100

#85210 — basic generator question

FromNeal Becker <ndbecker2@gmail.com>
Date2015-02-04 08:23 -0500
Subjectbasic generator question
Message-ID<mailman.18458.1423056240.18130.python-list@python.org>
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()

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).

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.



-- 
-- Those who don't understand recursion are doomed to repeat it

[toc] | [next] | [standalone]


#85222

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-02-05 03:09 +1100
Message-ID<54d24442$0$13001$c3e8da3$5496439d@news.astraweb.com>
In reply to#85210
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, there is no need for this "obj" class, it just adds a pointless
layer of indirection. Perhaps it was written by a Java programmer?

http://steve-yegge.blogspot.com.au/2006/03/execution-in-kingdom-of-nouns.html

Instead of:

x = obj(something_callable)
# later
result = x()

just do:

x = something_callable
result = x()

or even

result = something_callable()


 
> Now I want gen to be a callable that repeats N times.

What happens on the sixth time? The world ends? Most callables can be called
indefinitely.

I'm going to assume an exception. Later I'll use a RuntimeException, but you
can do anything you like.


> 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).
> 
> 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.

The built-in function `next` almost does what we want, except the exception
raised is inappropriate. Unless you are very careful, you don't want to
allow StopIteration to propagate, lest it be caught in an unexpected place
and cause surprises. (Not the pleasant kind.)


py> from functools import partial
py> f = partial(next, rpt("hello", 2)())  # note the extra parens
py> f()
'hello'
py> f()
'hello'
py> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


But I wouldn't use rpt as given. I'd say:

def repeat(obj, count):
    for i in range(count):
        yield obj
    raise RuntimeError  # or whatever

mycallable = partial(next, repeat("hello", 5))  # no extra parens

And now pass mycallable to your other class.



P.S. your naming conventions give me a blood clot. Class "rpt" taking an
argument "rpt" -- I lost six months of life just from reading that.


-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web