unintuitive for-loop behavior

Jussi Piitulainen jussi.piitulainen at helsinki.fi
Sun Oct 2 02:35:10 EDT 2016


Steve D'Aprano writes:

> On Sun, 2 Oct 2016 12:28 am, Jussi Piitulainen wrote:
>
>> I'm not sure any more to what message this should be a followup, but
>> here is a demonstration of two different semantics of the for-loop
>> variable scope/update, this time with nested loops using the same
>> loop variable name. The first function, tabulate, uses Python
>> semantics ("t" for true, if you like); the second, fabulate, is a
>> translation ("f" for false, if you like) that uses the magical
>> semantics where the loop variable is not only local to the loop but
>> also a different variable on each iteration.
>
> I'm sorry, I don't understand what you mean by "Python semantics" versus "a
> translation". A translation of what? In what way is it "magical semantics"?
> I see nothing magical in your code: it is Python code.

"Python semantics" is the semantics that Python actually uses when it
updated the variables of a for-loop. I would like to call it "assignment
semantics".

The second function is an executable translation of the first function
under a different semantics. I would like to call it "binding semantics"
to distinguish it from "assignment semantics", but that doesn't work
when people insist that "binding" and "assignment" are the same thing in
Python, so I called it "magical semantics" instead.

The method of using equivalent code as an explanation is known in Python
documentation, as in the explanation of list comprehensions in terms of
list.append and for-loops. This is what I called "translation" above. In
another community it might be called "syntactic transformation" or
"macro expansion".

> Of course, it is complex, complicated, convoluted, obfuscated, hard to
> understand, non-idiomatic Python code, but there's nothing magical in
> it (unless you count nonlocal as magic). And it does nothing that
> can't be done more simply: just change the tabulate inner loop
> variable to a different name.

It was stated, in this thread, that it would have been impossible to
make Python for-loops behave the way the corresponding Python code in my
translations of the two nested for-loops behaves. I thought it would be
a good idea to *show* how the "impossible" thing can be done.

I could have just posted that yes, it *could* be done, there's nothing
so special about variables and scope in Python. But I pretty much know
that the response to *that* would have been yet another round of "You
don't understand that Python variables are different, they are not boxes
in fixes locations but name bindings, and no, it cannot be done."

> def fabulate2(m, n):
>     # The simple, Pythonic, non-complicated way.
>     for i in range(m):
>         print(i, end = ': ')
>         c = 0
>         for j in range(n):
>             print(j, end = ', ' if j + 1 < n else ' : ')
>             c += 1
>         print(i, c)

It misses only the point of the exercise.

> Your version of tabulate and fabulate:
> py> tabulate(3, 4)
> 0: 0, 1, 2, 3 : 3 4
> 1: 0, 1, 2, 3 : 3 4
> 2: 0, 1, 2, 3 : 3 4
>
> py> fabulate(3, 4)
> 0: 0, 1, 2, 3 : 0 4
> 1: 0, 1, 2, 3 : 1 4
> 2: 0, 1, 2, 3 : 2 4
>
> My simple version of fabulate:
>
> py> fabulate2(3, 4)
> 0: 0, 1, 2, 3 : 0 4
> 1: 0, 1, 2, 3 : 1 4
> 2: 0, 1, 2, 3 : 2 4
>
>
>> The latter property makes no difference in this 
>> demonstration, but the former does; there's also a spurious counter that
>> is not local to the nested loops, just to be sure that it works as
>> expected (it does).
>> 
>> A summary of sorts: it's possible to demonstrate the scope difference in
>> Python code, with no box in sight; boxes are irrelevant; the relevant
>> issue is what function and when the loop variable is associated with,
>> explicitly or implicitly.
>
> I don't know what "scope difference" you think you are demonstrating.
> tabulate() has a single scope, fabulate() has multiple scopes because it
> has inner functions that take i as argument, making them local to the inner
> functions. Um, yeah, of course they are different. They're different
> because you've written them differently. What's your point?

The scope difference is the topic of this thread.

My point is that the for-loops could be translated/compiled/expanded
into the lower-level code so that the loop variables would be in their
own scopes.

> As far as I can see, all you have demonstrated is that it is possible to
> write obfuscated code in Python. But we already knew that.

The point is that the straightforward code *could* have the same meaning
as the "obfuscated" code. That for-loops *could* be magicking constructs
even in Python. (What word should I use instead of "magic"?)

The code might not seem so obfuscated to you if you thought of it not as
source code but as compiled code. Except it's still Python. What word
should I use instead of "translation"? Would "transformation" be
understood?



More information about the Python-list mailing list