[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Re: How to make an empty generator?

Robert Kern

2/18/2010 10:56:00 PM

On 2010-02-18 16:25 PM, Stephen Hansen wrote:
> This has to be a stupid question, but :)
>
> I have some generators that do stuff, then start yielding results. On
> occasion, I don't want them to yield anything ever-- they're only really
> "generators" because I want to call them /as/ a generator as part of a
> generalized system.
>
> The only way I can figure out how to make an empty generator is:
>
> def gen():
> # do my one-time processing here
>
> return
> yield
>
> Is there a better way? The return/yield just makes me flinch slightly. I
> tried just raising StopIteration at the end, but of course that didn't work.

class once(object):
def __init__(self, func, *args, **kwds):
self.func = func
self.args = args
self.kwds = kwds

def __iter__(self):
return self

def next(self):
self.func(*self.args, **self.kwds)
raise StopIteration()


Then write regular functions with the one-time processing code (not
generators!). When you go to pass them into your system that wants an iterator,
just wrap it with once(func).

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

11 Answers

Steven D'Aprano

2/18/2010 11:09:00 PM

0

Sorry for breaking the threading, but Stephen's original post hasn't come
through to my provider.

On 2010-02-18 16:25 PM, Stephen Hansen wrote:

> This has to be a stupid question, but :)
>
> I have some generators that do stuff, then start yielding results. On
> occasion, I don't want them to yield anything ever-- they're only
> really "generators" because I want to call them /as/ a generator as
> part of a generalized system.
>
> The only way I can figure out how to make an empty generator is:
>
> def gen():
> # do my one-time processing here
>
> return
> yield

If all you want is a generator that doesn't yield anything, then surely
there isn't any one-time processing and you don't need the comment?


>> Is there a better way? The return/yield just makes me flinch slightly.

Meh. An empty generator is a funny thing to do, so it's not bad that it
reads a bit funny. I don't have a problem with it.

If it really annoys you, you could do this:

def empty():
for x in []:
yield



--
Steven

Ben Finney

2/18/2010 11:33:00 PM

0

Robert Kern <robert.kern@gmail.com> writes:

> On 2010-02-18 16:25 PM, Stephen Hansen wrote:
> > The only way I can figure out how to make an empty generator is:
> >
> > def gen():
> > # do my one-time processing here
> >
> > return
> > yield
> >
> > Is there a better way? The return/yield just makes me flinch
> > slightly. I tried just raising StopIteration at the end, but of
> > course that didn't work.

No need to define functions or classes; let a generator expression take
care of it for you::

>>> foo = (x for x in list())
>>> foo.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

--
\ â??Value your freedom or you will lose it, teaches history. |
`\ â??Don't bother us with politics,â? respond those who don't want |
_o__) to learn.â? â??Richard Stallman, 2002 |
Ben Finney

Arnaud Delobelle

2/18/2010 11:49:00 PM

0

On 18 Feb, 23:33, Ben Finney <ben+pyt...@benfinney.id.au> wrote:
[...]
> No need to define functions or classes; let a generator expression take
> care of it for you::
>
>     >>> foo = (x for x in list())
>     >>> foo.next()
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in <module>
>     StopIteration

What about

foo = iter('')

Then there is the interesting

foo = iter(int, 0)

:)

--
Arnaud

Robert Kern

2/19/2010 12:12:00 AM

0

On 2010-02-18 17:33 PM, Ben Finney wrote:
> Robert Kern<robert.kern@gmail.com> writes:
>
>> On 2010-02-18 16:25 PM, Stephen Hansen wrote:
>>> The only way I can figure out how to make an empty generator is:
>>>
>>> def gen():
>>> # do my one-time processing here
>>>
>>> return
>>> yield
>>>
>>> Is there a better way? The return/yield just makes me flinch
>>> slightly. I tried just raising StopIteration at the end, but of
>>> course that didn't work.
>
> No need to define functions or classes; let a generator expression take
> care of it for you::
>
> >>> foo = (x for x in list())
> >>> foo.next()
> Traceback (most recent call last):
> File "<stdin>", line 1, in<module>
> StopIteration

He doesn't want *any* empty generator. He wants an iterator that executes some
given side-effect-producing code then immediately raises the StopIteration.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Ben Finney

2/19/2010 12:33:00 AM

0

Arnaud Delobelle <arnodel@googlemail.com> writes:

> What about
> foo = iter('')

That doesn't return a generator.

>>> foo = iter('')
>>> foo
<listiterator object at 0xf7cd3ed0>

Whether the OP needs to create a generator, or just any iterable type,
isn't clear.


Robert Kern <robert.kern@gmail.com> writes:

> He doesn't want *any* empty generator. He wants an iterator that
> executes some given side-effect-producing code then immediately raises
> the StopIteration.

Ah, hm. That's a rather perverse use case, but I'm sure the OP has their
reasons. It's going to confuse a reader who isn't expecting it, no
matter how simply it's done.

So, I think the best answer is what has already been suggested, but that
it's perverse enough that the hack *needs* a comment to say why it's
being done.

def make_empty_generator_with_side_effect():
""" Make a generator that does important work, but is empty. """

# Do the important work here.
spam = object()

# Make this function return an empty generator.
if False: yield

--
\ â??When cryptography is outlawed, bayl bhgynjf jvyy unir |
`\ cevinpl.â? â??Anonymous |
_o__) |
Ben Finney

Steven D'Aprano

2/19/2010 12:36:00 AM

0

On Thu, 18 Feb 2010 18:12:10 -0600, Robert Kern wrote:

> He wants an iterator that executes some given side-effect-producing code
> then immediately raises the StopIteration.

Ah, that's the bit I missed!

Yewww. Programming by side-effect... I hope the original poster has a
good reason for such a thing.


--
Steven

Robert Kern

2/19/2010 6:17:00 AM

0

On 2010-02-18 18:33 PM, Ben Finney wrote:
> Robert Kern<robert.kern@gmail.com> writes:
>
>> He doesn't want *any* empty generator. He wants an iterator that
>> executes some given side-effect-producing code then immediately raises
>> the StopIteration.
>
> Ah, hm. That's a rather perverse use case, but I'm sure the OP has their
> reasons.

Which he explained fairly clearly, I thought, in his original post.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Ben Finney

2/19/2010 7:02:00 AM

0

Robert Kern <robert.kern@gmail.com> writes:

> On 2010-02-18 18:33 PM, Ben Finney wrote:
> > Robert Kern<robert.kern@gmail.com> writes:
> >
> >> He doesn't want *any* empty generator. He wants an iterator that
> >> executes some given side-effect-producing code then immediately
> >> raises the StopIteration.
> >
> > Ah, hm. That's a rather perverse use case, but I'm sure the OP has their
> > reasons.
>
> Which he explained fairly clearly, I thought, in his original post.

(The original post isn't available to me; the reference in your reply
isn't accessible AFAICT.)

In the part of the original that you quoted, he speaks only of empty
generators (easy and clean), not generators that exist only for the
purpose of side-effects without yielding any items.

It's that latter that I describe as perverse, and I would think it worth
some effort to determine if that can be avoided by a different approach.

--
\ â??The problem with television is that the people must sit and |
`\ keep their eyes glued on a screen: the average American family |
_o__) hasn't time for it.â? â??_The New York Times_, 1939 |
Ben Finney

Arnaud Delobelle

2/19/2010 8:36:00 AM

0

Ben Finney <ben+python@benfinney.id.au> writes:

> Arnaud Delobelle <arnodel@googlemail.com> writes:
>
>> What about
>> foo = iter('')
>
> That doesn't return a generator.
>
> >>> foo = iter('')
> >>> foo
> <listiterator object at 0xf7cd3ed0>
>
> Whether the OP needs to create a generator, or just any iterable type,
> isn't clear.

If it walks and quacks like a duck... Anyway it's not just an iterable
object, it's an iterator. I can't really imagine that there would be
some code which would be happy with generators but not with iterators
(as long as you can't send anything to them, which is always the case
with an empty generator).

--
Arnaud

Ben Finney

2/19/2010 8:53:00 AM

0

Arnaud Delobelle <arnodel@googlemail.com> writes:

> Ben Finney <ben+python@benfinney.id.au> writes:
> > Whether the OP needs to create a generator, or just any iterable
> > type, isn't clear.
>
> If it walks and quacks like a duck... Anyway it's not just an iterable
> object, it's an iterator. I can't really imagine that there would be
> some code which would be happy with generators but not with iterators
> (as long as you can't send anything to them, which is always the case
> with an empty generator).

I can't imagine that someone would want to create a generator that's
always empty, but has some side-effect that is the *real* purpose for
using the generator.

Clearly, none of us should let our limited imaginations be the guide to
what people actually want to do.

--
\ â??Generally speaking, the errors in religion are dangerous; |
`\ those in philosophy only ridiculous.â? â??David Hume, _A Treatise |
_o__) of Human Nature_, 1739 |
Ben Finney