[Python-Dev] Visibility scope for "for/while/if" statements

Alexander Myodov maa_public at sinn.ru
Thu Sep 22 19:24:30 CEST 2005

Hello Josiah,

>>  Why the variables defined inside "for"/"while"/"if" statements
>>  (including loop variables for "for") are visible outside this scope?
JC> if and while statements don't define variables, so they can't expose
JC> them later in the scope.
They don't. They just leak internal ones:
i = 0
while i != 1:
    i += 1
    j = 5
print j

JC> In regards to 'for' loops, they have always done that, there is code
JC> that relies on that behavior, and changing behavior would unnecessarily
JC> break code.
I mentioned it below: while unconditional changing the behaviour will
definitely break a lot, something like "import strict" would help
those ones who rate such behaviour enough error-prone to
reconsider proceeding using Python at all.

JC> Further, you should clarify what you would want this mythical non-leaky
JC> for loop to do in various cases.  What would happen in the following
JC> case?

JC>     i = None
JC>     for i in ...:
JC>         ...
JC>     print i
JC> ... assuming that the loop executed more than once?  Would you always
JC> get 'None' printed, or would you get the content of the last variable?
As for me (if my humble opinion is useful for you), the best would be
to 1. assume that a loop variable is always newly-declared for this
loop, 2. all variables first declared inside the loop are local to this
Thus, your example falls to case 1: "i" variable is newly declared for
this loop. Well, we don't reuse old value of i to start the iteration
from a particular place, like below?

i = 5
for i in [3,4,5,6,7]:
    print i,

More general, the variables could be assumed local only to the *same
or higher* indentation level. 

JC> What about:
JC>     x = None
JC>     for i in ...:
JC>         x = f(i)
JC>         ...
JC>     print x
JC> Would 'x' be kept after the loop finished executing?
case 2: "x" variable is declared already. And if there is no
"x = None" line, it should tell "name 'x' is not defined". Unless we
are prone to funny "uncertainly defined" cases, if some variable is
defined inside an "in" in the loop.

JC> I would imagine in your current code you are running something like
JC> this:

JC>     i = #some important value
JC>     ... #many lines of code
JC>     for i in ...:
JC>         ...
JC>     #you access the 'i' you bound a long time ago

JC> In this case, you are making a common new programmer mistake by using
JC> the same variable name for two disparate concepts.
Nah, here is my error-case:
I made several loops, one by one, using the "i" variable for looping.
Then in the latest loop I changed the "i" name to more meaningful
"imsi" name in the "for" declaration and whenever I found inside the loop.
As I use "i" name *for loops exclusively*, I didn't wittingly reuse the
same name for different purposes. The problem was that I missed one
occurance of "i" variable inside the loop code, so it gained the same
value (from the completion of previous loop) throughout all the "imsi"
loop. And the interpreter didn't notice me that "I am using the
undefined variable" (since it is considered defined in Python), as
accustomed from other languages. That's my sorrowful story.

JC> If the 'i' that was
JC> initially bound was important through the lifetime of the scope, you
JC> should have named it differently than the 'i' that was merely a loop
JC> variable.
I'm pretty happy that I didn't ever made a list comprehension with "i"
variable inside the loop over "i" variable. While I wasn't aware of
these side-effects, it would be even harder spottable. Now I'll look
more carefully at copy-pasting list comprehensions, in every case
examining all of the lower-indent variables for not to clash.

JC> I will also point out that in general, not leaking/exposing/etc. such
JC> variables would necessarily slow down Python.  Why?
I agree, this is one of obvious advantages of absence of
pseudo-namespaces (wasting the resources to allocation and removal of
variables, etc). Though in case of presence of pseudo-namespaces, it
an easily be emulated by initializing the variable first-time on the
highest-level of indentation.
But for the "performance-oriented/human-friendliness" factor, Python
is anyway not a rival to C and similar lowlevellers. C has
pseudo-namespaces, though.

JC> Python semantics seem to have been following the rule of "we are all
JC> adults here".
I always believed that the programming language (as any computer
program) should slave to the human, rather than a human should slave
to the program.

JC> Generally though, Python follows a common C semantic of variable leakage.

JC> C Code:
JC>     int i; // required in some versions of C
JC>     for (i=0;i<10;i++) {
JC>         ...
JC>     }
"for (int i = 0; i < 10; i++)" works fine nowadays.

JC> Again: test your assumptions.  If your untested assumptions are wrong,
JC> don't complain that the language is broken.
In my case, as I explained already, it was not a assumption but an
uncatched mistype, which is usually catched in other languages due to
the presence of "pseudo-namespaces" (and in other languages I even
accustomed to enforce the locality of temporary variables by
explicitly setting the logically independent blocks of code within the
curly braces). I always test the doubtful pieces before use. But
*I don't dare to tell that the language is broken*. The existing
behaviour has its own pros, and I also don't want a lot of code
to be broken by easy behaviour change. What upsets me is
the absence of alternatives (as the lack of flexibility) for the new
code, especially with the fact that current behaviour mismatches with
many of currently popular languages and habits learned from them.

JC> Also: python-dev is a mailing list for the development /of/ Python.
JC> Being that your questions as of late have been in the realm of "why does
JC> or doesn't Python do this?", you should go to python-list (or the
JC> equivalent comp.lang.python newsgroup) for answers to questions
JC> regarding current Python behavior, and why Python did or didn't do
JC> something in its past.
I'm sorry for wasting the time of developers. For "for/while/if"
statements, I just had an idea which (I believed) could be useful for
many peoples, and could be very useful for such a human-orienter
language as Python is (actually, this idea is borrowed from another
language, but only partly - only in the area of ability to have "for"
and "while" inside the single loop expression), so I though that the
best people to estimate it should be the ones who potentially could
implement this (provided they like it). For this conversation, the
explained just looked to me as language-level problem (especially for list
comprehensions), so I had to beg a workaroung/explanation/fix to it
also from the language creators. If they don't consider it a problem
and don't have a workaroung - sorry again for wasting your time,
then that's indeed only my problem and I'll try to cope with it
I really didn't want to "claim and blame". What I asked and proposed
was intended to be useful not only for myself, but - I believed - for
many people, especially newcomers after the other languages.

С уважением,
 Alexander                          mailto:maa_public at sinn.ru

More information about the Python-Dev mailing list