[Python-Dev] Lexical scoping in Python 3k
Guido van Rossum
guido at python.org
Mon Jul 3 17:45:49 CEST 2006
On 7/3/06, Andrew Koenig <ark at acm.org> wrote:
> > I don't think "trivial" is the right word to use here,
> > since it implies something that's of so little importance
> > that it can be ignored. But the simple cases are precisely
> > the ones where this wart hurts the most, so we can't
> > ignore them.
>
> I'd like to inject an example that might help make this discussion more
> concrete.
>
> Consider the following function:
>
> def for_each(seq, f):
> for i in seq:
> f(i)
>
> I'm sure I've seen more than one instance of someone on comp.lang.python
> trying to do the equivalent of using a function such as this one to compute
> the sum of the elements of a sequence as follows:
>
> def sum(seq):
> result = 0
> def accum(i):
> result += i
> for_each(seq, accum)
> return result
>
> and wonder why it doesn't work. Still odder, why it doesn't work and the
> following does:
>
> def sum(seq):
> result = [0]
> def accum(i):
> result[0] += i
> for_each(seq, accum)
> return result[0]
>
> Transforming the first definition of sum above into the second may be
> trivial, but only if you've encountered the technique before. Moreover, the
> first version of sum uses a technique that is more than 45 years old (!), as
> it was available to Algol 60 programmers.
Much though the Algol 60 tickles my nostalgia (it was my first
programming language!) I don't think that it's a particularly strong
argument. I like to think that we have better ways these days.
I think you need to come up with a better motivating example; the
above is particular un-idiomatic Python. It starts by defining a
higher-order function for_each that has little to offer over writing
an explicit for loop, and then uses this to motivate writing a simple
operation (result += i) as a function instead so that it fits in the
inconvenient for_each() API.
I understand that both for_each() and accum() are just examples of
more complicated functions, but I can't help thinking that the problem
here only occurs for very *simple* functions in the place of accum();
a more complicated form of accum would likely be a bound method of a
class instance which carries the state.
A better way to decompose these kinds of problems is probably by using
generators. The equivalent of for_each() would not take a function
parameter but *yield* the successive values instead of calling f()
with successive values; e.g.:
def for_each(seq):
for i in seq:
yield i
Then the sum() function could be written like this:
def sum(seq):
result = 0
for i in for_each(seq):
result += i
return result
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-Dev
mailing list