lambda in list comprehension acting funny
steve+comp.lang.python at pearwood.info
Sun Jul 15 01:29:02 CEST 2012
On Fri, 13 Jul 2012 12:54:02 -0600, Ian Kelly wrote:
> On Fri, Jul 13, 2012 at 11:53 AM, Hans Mulder <hansmu at xs4all.nl> wrote:
>> The function `function` refers to a variable `VERBOSE` that isn't
>> local. In some programming langauages, the interpreter would then scan
>> the call stack at run-time, looking for a scope where that name is
>> defined. It would find the local one in `caller`. This is known as
>> "dynamic binding".
>> Other interpreters use the `VERBOSE` that was in scope at the point in
>> the program text where `function` was defined. In this case, that would
>> be the global one. This is called "lexical binding".
>> Some programming languages allow you to indicate on a per- variable
>> basis whether you want dynamic or lexical binding.
>> Python is firmly in the lexical camp. Dynamic binding is not available
>> in Python, and never will be.
binding, but whichever it is, it is generally considered to be a bad
idea, at least as the default or only behaviour.
Bash is another language with dynamic binding. Some very old versions of
Lisp use dynamic binding, because it was the easiest to implement. Most
modern languages use lexical (also known as static) binding, because it
is more sensible.
Here is an illustration of the difference: suppose we have two modules,
library.py and main.py:
x = 23
return x + y
x = 1000
If main.py prints 24 (and it does), then Python is using lexical scoping.
But if it prints 1001 (which it doesn't), then it is using dynamic
scoping. The obvious problem with dynamic binding is that the behaviour
of a function may vary depending on where you call it.
> I don't believe that dynamic vs. lexical binding is what rusi was
> attempting to describe. If he was, then Python and Haskell would be a
> bad comparison since both are lexical. Rather, I think what he was
> trying to show was capture by reference vs. capture by value in the
> context of closures. Python uses capture by reference, and so the
> upvalue is the value of that reference at the time the closure is
> called. Haskell uses capture by value, and the upvalue is the value at
> the time of definition.
I don't think "by reference" versus "by value" are good terms to use
here, since they risk conflating the issue with "call by reference"
versus "call by value" semantics. I prefer "late" versus "early", as you
> I've also seen the distinction described as "early" vs. "late" binding
> on this list, but I'm not sure how precise that is -- I believe that
> terminology more accurately describes whether method and attribute names
> are looked up at compile-time or at run-time,
Not necessarily *compile* time, but the distinction is between when the
function is defined (which may at compile time, or it may be at run time)
versus when the function is called. I think that gets to the heart of the
issue, not whether the capture copies a value or a reference. At some
point, the capture must make use of the value: whether it does so via a
direct C-style memory location copy, or an object pointer, or some other
mechanism, is irrelevant. What matters is whether that value is grabbed
at the time the closure is created, or when the closure is called.
> late binding being the
> feature that makes duck typing possible.
That is conflating two entirely distinct subjects. Python 1.5 had duck-
typing but no closures, so the one certainly does not depend on the other.
Duck-typing is more a philosophy than a language feature: the language
must be typed, and the programmer must prefer to program to a protocol or
a specification rather than to membership of a type.
More information about the Python-list