How to make an empty generator?
apt.shansen at gmail.com
Fri Feb 19 18:44:16 CET 2010
On Fri, Feb 19, 2010 at 9:21 AM, Steven D'Aprano <
steve at remove-this-cybersource.com.au> wrote:
> On Fri, 19 Feb 2010 09:51:54 -0600, Robert Kern wrote:
> >> 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.
What does it matter what *do stuff* means? My point is, there's *stuff* I
need to do there, and what that stuff is really has absolutely nothing to do
with the issue at hand. Its certainly a side-effect, at least in terms of
the generator, otherwise there would be no point really in having the
generator there at all.
I have a system that consumes generators which, almost always, yield over
objects to be handled. One in ten-- nay, one in 20, if not worse-- cases has
me wanting to inject into this system some arbitrary code that gets run.
Some bit of processing I need to get done in the context of that cycle.
There's nothing harmful about it. These aren't generic generators that are
going to be passed around and consumed by random things or anything else.
They exist solely to be consumed by the core system. They're never composed
or loaded by anything else, its just the API of how the system works. It
loads bunches of modules dynamically, each module has a generator for
yielding objects to be consumed. That generator is the one and only line of
connection between the core system and the modules.
> > 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.
It doesn't matter what the one-time processing is supposed to be. I could
say, "This particular module doesn't yield objects like all the rest, but
instead just needs to override a certain utility function the system uses,
to change how name equality is handled so that tests compare on normalized
forms. The API for integrating into the the core system -- to be loaded as a
module and integrated into the system -- is to have a generator of a certain
name, which yields N objects. In this case, N = 0.".
Now, having said that, why in the world does that matter at all to my
question? :) It changes no part of anyone's possible solution, be it
Robert's once-wrapped-to-decorator, to Holden's just-comment-the-oddity, to
your empty-for-loop-yield, to any others.
It doesn't *matter* what the processing has to be. And if it has
side-effects or not is only relevant to the question of the perversity of my
use-case, a discussion I just don't really even have any interest in =)
Thanks, all, though, for your responses and solutions.
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
# do one time processing here
A generator is just a callable that returns an iterator, after all. If I
don't want to yield anything, returning an empty iterable accomplishes the
same goal to get the code loaded and run by the host-cycle while
contributing nothing at all to the object pool.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-list