Explanation of this Python language feature? [x for x in x for x in x] (to flatten a nested list)

Steven D'Aprano steve at pearwood.info
Tue Mar 25 02:52:13 EDT 2014


On Mon, 24 Mar 2014 21:39:33 -0500, Mark H Harris wrote:

> On 3/24/14 8:20 PM, Terry Reedy wrote:
>> On 3/24/2014 7:56 PM, Mark H Harris wrote:
> 
>>> the list which is used for each of the adder[] functions created.
>>
>> Wrong. Functions look up global and nonlocal names, such as n, when the
>> function is called.
>>
>>
> hi Terry, yeah, I know; this is what's *wrong* all at once.
> 
> Functions "look up global and nonlocal names" such as n, is semantics
> for "each created function 'grabs' the last number (n) in the list",
> well, because that (n) is bound at call-time to (3).
> 
> Your version semantically is detailed and correct; my version
> semantically is "how it is perceived" by the user, which is also
> correct.

No it isn't. You can demonstrate that some mental models are closer to 
the actual behaviour of the interpreter, while other models are 
incorrect, by writing just a little more complex code. 


py> def test(arg):
...     results = []
...     for n in [1, 2, 3, 4]:
...         results.append(lambda: n)
...     n = arg
...     return results
... 
py> for func in test(1000):
...     print(func())
... 
1000
1000
1000
1000


The functions don't grab the last value from the list. They see whatever 
value the variable n has at the time the function is called.

Are you surprised by this? If you are, it is because you haven't thought 
it through in any detail. Let me show you something superficially 
different:


py> funcs = []
py> for n in [1, 2, 3, 4]:
...     def f():
...             return n
...     funcs.append(f)
... 
py> n = 1000
py> for f in funcs:
...     print(f())
... 
1000
1000
1000
1000


Are you still surprised? I bet you aren't. How else would you expect a 
variable to work?


Early binding may be *useful* sometimes, but it would be terribly 
surprising if it were the default:

my_name = "Fred"
def greet():
    print("Hello", my_name)

my_name = "Barney"
greet()

Would you expect to see "Hello Fred"?

The problem here is that Python is consistent, but people *want* it to be 
inconsistent. When it doesn't magically read their mind, they get 
"confused" that it isn't working the way they "expected".




-- 
Steven



More information about the Python-list mailing list