Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #85210 > unrolled thread
| Started by | Neal Becker <ndbecker2@gmail.com> |
|---|---|
| First post | 2015-02-04 08:23 -0500 |
| Last post | 2015-02-05 03:09 +1100 |
| Articles | 2 — 2 participants |
Back to article view | Back to comp.lang.python
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
| From | Neal Becker <ndbecker2@gmail.com> |
|---|---|
| Date | 2015-02-04 08:23 -0500 |
| Subject | basic 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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2015-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