Re: How to make an empty generator?

Discussion in 'Python' started by Robert Kern, Feb 18, 2010.

  1. Robert Kern

    Robert Kern Guest

    On Feb 18, 5:08 pm, Steven D'Aprano <> wrote:
    > 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?


    Sure there is. Python doesn't know that nothing gets yielded until it hits the
    return statement before the yield. When it calls .next() on the iterator, the
    code elided by the comment executes, then the return is hit, a StopIteration
    exception is raised, and the iteration is complete.

    --
    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
    Robert Kern, Feb 18, 2010
    #1
    1. Advertising

  2. On Thu, 18 Feb 2010 17:30:54 -0600, Robert Kern wrote:

    > > 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?

    >
    > Sure there is. Python doesn't know that nothing gets yielded until it
    > hits the return statement before the yield. When it calls .next() on the
    > iterator, the code elided by the comment executes, then the return is
    > hit, a StopIteration exception is raised, and the iteration is complete.


    I don't understand why you care about having *any* code before the
    StopIteration. That's like:

    def empty():
    for x in range(1000):
    pass # Spin wheels uselessly
    return
    yield


    What's the point of the wheel spinning? Did I miss something?



    --
    Steven
    Steven D'Aprano, Feb 19, 2010
    #2
    1. Advertising

  3. Robert Kern

    Mel Guest

    Steven D'Aprano wrote:

    > On Thu, 18 Feb 2010 17:30:54 -0600, Robert Kern wrote:
    >
    >> > 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?

    >>
    >> Sure there is. Python doesn't know that nothing gets yielded until it
    >> hits the return statement before the yield. When it calls .next() on the
    >> iterator, the code elided by the comment executes, then the return is
    >> hit, a StopIteration exception is raised, and the iteration is complete.

    >
    > I don't understand why you care about having *any* code before the
    > StopIteration. That's like:
    >
    > def empty():
    > for x in range(1000):
    > pass # Spin wheels uselessly
    > return
    > yield
    >
    >
    > What's the point of the wheel spinning? Did I miss something?


    I wonder whether it's for some kind of framework with a main loop like

    for it in list_of_iterables:
    for x in it:
    do_this_or_that (x)

    where, every once in a while one wants to throw some arbitrary code into the
    process, in the form of an empty iterable with side effects.

    Mel.
    Mel, Feb 19, 2010
    #3
  4. Robert Kern

    Robert Kern Guest

    On 2010-02-18 19:28 PM, Mel wrote:
    > Steven D'Aprano wrote:
    >
    >> On Thu, 18 Feb 2010 17:30:54 -0600, Robert Kern wrote:
    >>
    >>> > 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?
    >>>
    >>> Sure there is. Python doesn't know that nothing gets yielded until it
    >>> hits the return statement before the yield. When it calls .next() on the
    >>> iterator, the code elided by the comment executes, then the return is
    >>> hit, a StopIteration exception is raised, and the iteration is complete.

    >>
    >> I don't understand why you care about having *any* code before the
    >> StopIteration. That's like:
    >>
    >> def empty():
    >> for x in range(1000):
    >> pass # Spin wheels uselessly
    >> return
    >> yield
    >>
    >>
    >> What's the point of the wheel spinning? Did I miss something?

    >
    > I wonder whether it's for some kind of framework with a main loop like
    >
    > for it in list_of_iterables:
    > for x in it:
    > do_this_or_that (x)
    >
    > where, every once in a while one wants to throw some arbitrary code into the
    > process, in the form of an empty iterable with side effects.


    Yes. That is exactly what the OP said in his original post:

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

    --
    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
    Robert Kern, Feb 19, 2010
    #4
  5. On Fri, 19 Feb 2010 00:15:20 -0600, Robert Kern wrote:

    >>> What's the point of the wheel spinning? Did I miss something?

    >>
    >> I wonder whether it's for some kind of framework with a main loop like
    >>
    >> for it in list_of_iterables:
    >> for x in it:
    >> do_this_or_that (x)
    >>
    >> where, every once in a while one wants to throw some arbitrary code
    >> into the process, in the form of an empty iterable with side effects.

    >
    > Yes. That is exactly what the OP said in his original post:
    >
    > """
    > 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. """



    But he doesn't say anything about side-effects. If you're passing
    generators around, sometimes you want an empty generator, just as
    sometimes you want an empty string, or list, or whatever.



    --
    Steven
    Steven D'Aprano, Feb 19, 2010
    #5
  6. Robert Kern

    Robert Kern Guest

    On 2010-02-19 00:21 AM, Steven D'Aprano wrote:
    > On Fri, 19 Feb 2010 00:15:20 -0600, Robert Kern wrote:
    >
    >>>> What's the point of the wheel spinning? Did I miss something?
    >>>
    >>> I wonder whether it's for some kind of framework with a main loop like
    >>>
    >>> for it in list_of_iterables:
    >>> for x in it:
    >>> do_this_or_that (x)
    >>>
    >>> where, every once in a while one wants to throw some arbitrary code
    >>> into the process, in the form of an empty iterable with side effects.

    >>
    >> Yes. That is exactly what the OP said in his original post:
    >>
    >> """
    >> 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. """

    >
    > But he doesn't say anything about side-effects.


    "I have some generators *that do stuff*, then start yielding results." [emphasis
    mine]. Then he gives an example of a generator that does side-effect stuff and
    returning before yielding anything.

    --
    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
    Robert Kern, Feb 19, 2010
    #6
  7. On Fri, 19 Feb 2010 09:51:54 -0600, Robert Kern wrote:

    > On 2010-02-19 00:21 AM, Steven D'Aprano wrote:
    >> On Fri, 19 Feb 2010 00:15:20 -0600, Robert Kern wrote:
    >>
    >>>>> What's the point of the wheel spinning? Did I miss something?
    >>>>
    >>>> I wonder whether it's for some kind of framework with a main loop
    >>>> like
    >>>>
    >>>> for it in list_of_iterables:
    >>>> for x in it:
    >>>> do_this_or_that (x)
    >>>>
    >>>> where, every once in a while one wants to throw some arbitrary code
    >>>> into the process, in the form of an empty iterable with side effects.
    >>>
    >>> Yes. That is exactly what the OP said in his original post:
    >>>
    >>> """
    >>> 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. """

    >>
    >> But he doesn't say anything about side-effects.

    >
    > "I have some generators *that do stuff*, then start yielding results."
    > [emphasis mine].


    What does "do stuff" have to do with side-effects? Here's a generator
    that does stuff, and it has no side-effects.

    def generator_that_does_stuff(x):
    y = 3*x**2 - 5*x + 1
    yield y

    "Do stuff" is ambiguous -- it could mean stuff with side-effects, or
    stuff without. The first is potentially harmful, the second is pointless.


    > Then he gives an example of a generator that does
    > side-effect stuff and returning before yielding anything.


    Unfortunately the OP's original post isn't visible to me, so I can only
    respond to your post, which may or may not quote the entire original post.

    The only example I have seen was an empty generator with a comment saying
    "do my one-time processing here", with *no* indication of what that one-
    time processing is supposed to be, why it is necessary, and whether it
    has side-effects or not.

    Since the OP (apparently) hasn't seen fit to comment, we're still all
    guessing what he means. It's certainly possible, likely even, that he's
    using generators that operate by side-effect: that explanation is
    consistent with his request. Personally, I can't imagine that would be
    good coding practice, but I could be wrong.


    --
    Steven
    Steven D'Aprano, Feb 19, 2010
    #7
  8. Robert Kern

    Terry Reedy Guest

    On 2/19/2010 12:44 PM, Stephen Hansen wrote:

    > Much to my embarrassment, sometime last night I realized I was being a
    > complete idiot, and the 'correct' way to handle this in my scenario is
    > really just:
    >
    > def initialize():
    > # do one time processing here
    >
    > return []
    >
    > A generator is just a callable that returns an iterator, after all.


    Confusing generators and generator functions is, well, confusing.
    For future reference, and clarity of communication in Pythonland,

    generator function: function that produces a generator when called; if
    python coded, its body contains 'yield'.

    generator: iterator produced by a generator function; has .__next__ and
    self-returning .__init__, like all other iterators.

    generator expression: an expression that evaluates to a generator; the
    expression is used to create a temporary anonymous generator function
    that is called to produce the generator and is then discarded.

    >>> def gf(): yield 1


    >>> gf

    <function gf at 0x00F5F4B0>
    >>> g=gf()
    >>> g

    <generator object gf at 0x00F5BE40>
    >>> ge = (1 for i in [1])
    >>> ge

    <generator object <genexpr> at 0x00F5BFD0>
    >>> dir(ge)

    [..., '__iter__', ..., '__next__', ...]

    So, when you said that you send 'generators' to your core system, when
    you meant 'generator functions', we were understanably confused. (Your
    core system should accept iterator classes also, unless it specifically
    checks to avoid duck typing.)

    Terry Jan Reedy
    Terry Reedy, Feb 19, 2010
    #8
  9. Robert Kern

    John Posner Guest

    On 2/19/2010 2:25 PM, Terry Reedy wrote:
    > On 2/19/2010 12:44 PM, Stephen Hansen wrote:
    >
    >> Much to my embarrassment, sometime last night I realized I was being a
    >> complete idiot, and the 'correct' way to handle this in my scenario is
    >> really just:
    >>
    >> def initialize():
    >> # do one time processing here
    >>
    >> return []
    >>
    >> A generator is just a callable that returns an iterator, after all.

    >
    > Confusing generators and generator functions is, well, confusing.
    > For future reference, and clarity of communication in Pythonland,
    >
    > generator function: function that produces a generator when called; if
    > python coded, its body contains 'yield'.
    >
    > generator: iterator produced by a generator function;


    I suggest:

    iterator produced by a generator function or a generator expression;

    has .__next__ and
    > self-returning .__init__, like all other iterators.
    >
    > generator expression: an expression that evaluates to a generator; the
    > expression is used to create a temporary anonymous generator function
    > that is called to produce the generator and is then discarded.


    Note that the Py2.6.4 documentation is inconsistent. AFAICT, it conforms
    to Terry's definitions above in most places. But the Glossary says:

    generator
    A function which returns an iterator. <... more ...>

    generator expression
    An expression that returns a generator. <... more ...>

    The additional verbiage in these definitions mitigates the damage, but I
    think the first entry should be headlined *generator function* instead
    of *generator*. And the Glossary should include Terry's additional entry
    [ as amended by me :) ]:

    generator
    An iterator produced by a generator function or a generator
    expression.

    -John
    John Posner, Feb 19, 2010
    #9
  10. Robert Kern

    Steve Holden Guest

    John Posner wrote:
    > On 2/19/2010 2:25 PM, Terry Reedy wrote:
    >> On 2/19/2010 12:44 PM, Stephen Hansen wrote:
    >>
    >>> Much to my embarrassment, sometime last night I realized I was being a
    >>> complete idiot, and the 'correct' way to handle this in my scenario is
    >>> really just:
    >>>
    >>> def initialize():
    >>> # do one time processing here
    >>>
    >>> return []
    >>>
    >>> A generator is just a callable that returns an iterator, after all.

    >>
    >> Confusing generators and generator functions is, well, confusing.
    >> For future reference, and clarity of communication in Pythonland,
    >>
    >> generator function: function that produces a generator when called; if
    >> python coded, its body contains 'yield'.
    >>
    >> generator: iterator produced by a generator function;

    >
    > I suggest:
    >
    > iterator produced by a generator function or a generator expression;
    >
    > has .__next__ and
    >> self-returning .__init__, like all other iterators.
    >>
    >> generator expression: an expression that evaluates to a generator; the
    >> expression is used to create a temporary anonymous generator function
    >> that is called to produce the generator and is then discarded.

    >
    > Note that the Py2.6.4 documentation is inconsistent. AFAICT, it conforms
    > to Terry's definitions above in most places. But the Glossary says:
    >
    > generator
    > A function which returns an iterator. <... more ...>
    >
    > generator expression
    > An expression that returns a generator. <... more ...>
    >
    > The additional verbiage in these definitions mitigates the damage, but I
    > think the first entry should be headlined *generator function* instead
    > of *generator*. And the Glossary should include Terry's additional entry
    > [ as amended by me :) ]:
    >
    > generator
    > An iterator produced by a generator function or a generator
    > expression.
    >
    > -John
    >

    +1. Can someone submit a documentation patch, please?

    regards
    Steve
    --
    Steve Holden +1 571 484 6266 +1 800 494 3119
    PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
    Holden Web LLC http://www.holdenweb.com/
    UPCOMING EVENTS: http://holdenweb.eventbrite.com/
    Steve Holden, Feb 24, 2010
    #10
  11. Robert Kern

    John Posner Guest

    On 2/24/2010 9:07 AM, Steve Holden wrote:
    > John Posner wrote:


    >> Note that the Py2.6.4 documentation is inconsistent. AFAICT, it conforms
    >> to Terry's definitions above in most places. But the Glossary says:
    >>
    >> generator
    >> A function which returns an iterator.<... more ...>
    >>
    >> generator expression
    >> An expression that returns a generator.<... more ...>
    >>
    >> The additional verbiage in these definitions mitigates the damage, but I
    >> think the first entry should be headlined *generator function* instead
    >> of *generator*. And the Glossary should include Terry's additional entry
    >> [ as amended by me :) ]:
    >>
    >> generator
    >> An iterator produced by a generator function or a generator
    >> expression.
    >>
    >> -John
    >>

    > +1. Can someone submit a documentation patch, please?
    >


    Will do. -John
    John Posner, Feb 24, 2010
    #11
  12. Robert Kern

    John Posner Guest

    >>> generator
    >>> An iterator produced by a generator function or a generator
    >>> expression.
    >>>
    >>> -John
    >>>

    >> +1. Can someone submit a documentation patch, please?
    >>

    >
    > Will do. -John


    [sorry if this is a dup]

    Done: #8012 "Revise generator-related Glossary entries"

    -John
    John Posner, Feb 24, 2010
    #12
  13. Robert Kern

    Aahz Guest

    In article <>,
    Terry Reedy <> wrote:
    >
    >Confusing generators and generator functions is, well, confusing.
    >For future reference, and clarity of communication in Pythonland,
    >
    >generator function: function that produces a generator when called; if
    >python coded, its body contains 'yield'.
    >
    >generator: iterator produced by a generator function; has .__next__ and
    >self-returning .__init__, like all other iterators.
    >
    >generator expression: an expression that evaluates to a generator; the
    >expression is used to create a temporary anonymous generator function
    >that is called to produce the generator and is then discarded.


    My preference is to use the terms "generator" and "generator iterator"
    (abbreviated "gen iter" or "geniter").
    --
    Aahz () <*> http://www.pythoncraft.com/

    "Many customs in this life persist because they ease friction and promote
    productivity as a result of universal agreement, and whether they are
    precisely the optimal choices is much less important." --Henry Spencer
    Aahz, Feb 24, 2010
    #13
  14. Am 24.02.2010 23:58, schrieb Aahz:
    > (abbreviated "gen iter" or "geniter").


    lol I don't know why, but this sounds like a sex toy to me ;)

    Regards,
    Michael
    Michael Rudolf, Feb 24, 2010
    #14
  15. Robert Kern

    Aahz Guest

    In article <hm4bh2$3k4$-heidelberg.de>,
    Michael Rudolf <> wrote:
    >Am 24.02.2010 23:58, schrieb Aahz:
    >>
    >> (abbreviated "gen iter" or "geniter").

    >
    >lol I don't know why, but this sounds like a sex toy to me ;)


    <smirk> And I thought only smutty Americans would have that twitch.
    --
    Aahz () <*> http://www.pythoncraft.com/

    "Many customs in this life persist because they ease friction and promote
    productivity as a result of universal agreement, and whether they are
    precisely the optimal choices is much less important." --Henry Spencer
    Aahz, Feb 24, 2010
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin Maurer
    Replies:
    3
    Views:
    4,783
    Peter
    Apr 19, 2006
  2. TheDustbustr
    Replies:
    1
    Views:
    437
    Sami Hangaslammi
    Jul 25, 2003
  3. Replies:
    9
    Views:
    531
  4. Chris Withers

    Problems with email.Generator.Generator

    Chris Withers, Sep 11, 2006, in forum: Python
    Replies:
    20
    Views:
    1,673
    Max M
    Sep 12, 2006
  5. Robert Kern

    Re: How to make an empty generator?

    Robert Kern, Feb 18, 2010, in forum: Python
    Replies:
    7
    Views:
    582
    Robert Kern
    Feb 19, 2010
Loading...

Share This Page