wow! (generators) - suggestion (yield saved)

Tim Peters tim.one at home.com
Sun Aug 12 01:04:43 EDT 2001


[Quinn Dunkan]
> ...
> Generators are cool, but I think they have a danger of other
> "cool" features:  the urge to use them when you don't really need them.

The criteria should be what's easiest to read a year later; "need" has
nothing to do with it <wink>.

> I fall into this with list comprehensions all the time.  I'll need
> some simple operation, and write
> [ f(x) for x in a ].  Then I'll need to do some more, so I'll write
> [ g(f(x)) for x in a + b ].  I wind up with things like
>
> for k, v in [ k.strip(), v.strip() for k, v in line.split('=')
>                 for line in open(self.config_file).readlines()
>                 if not line.beginswith('#') ]:
>     self.dict[k] = v
>
> ... which I quickly dismantle and rewrite as a series of statements
> in the loop, which I'll have to do anyway if I want the "parsing" to
> be smarter.  I should have started with a loop in the first place.

Why?  Believe it or not, lines of Python code have no egos, and truly aren't
offended when they're thrown away.  To the contrary, a listcomp is deeply
offended when you stuff too much between its brackets.  They're slim little
things, excellent as bookends but too insubstantial to support oceans of
vertical space.  You're simply sensitive to their tortured screams, and
that's a *good* thing!

> I have a feeling that myself and others are going to feel tempted to
> use generators when a list would be more flexible and easier to
> understand.

Well, we already see that happening, and the feature hasn't even been
released yet.  People with a "everything is a space potato!" bent will try
to use space potatoes for everything, and there's simply no hope for them
short of coming back to Earth.

from __future__ import generators

def range(start, stop):
    if start >= stop:
        return
    code = "def inner():\n"
    i = start
    while i < stop:
        code += " yield %r\n" % i
        i += 1
    d = {}
    exec code in d
    for x in d['inner']():
        yield x

for i in range(10L**20, 10L**20+3):
    print i

This is probably not the best way to extend range() to handle Python longs,
but I expect to see it submitted as a patch within a week <wink>.

> They make it easy to give yourself an "it'll be more efficient"
> rationale, and we all know how misleading those are.  Besides,
> they're just plain nifty.  Like list comprehensions, I'll be
> (subconciously, perhaps) *looking* for uses for them.

That's not bad!  Playing with features is a good way to learn their
limitations, and discover their natural niches.  Just clean up your mess
when it's time to go home.

guilt-is-your-friend-companion-and-infallible-guide-ly y'rs  - tim





More information about the Python-list mailing list