Safely using for-loop variables outside the loop
<p><a href="http://stackoverflow.com/a/3611987/336527">Most arguments</a> about why the design decision was made to make for-loop variables <em>not</em> local to the loop suggest that there are popular use cases.</p>

<p>The obvious use case is this:</p>

<pre><code>x = default_value
for x in iterator:
    # do stuff
# do something with x here
</code></pre>

<p>Unfortunately, often the first line is forgotten:</p>

<pre><code># should have set default value for x here
# but forgot
for x in iterator:
    # do stuff
# do something with x here
</code></pre>

<p>So when iterator is empty, they raise <code>NameError</code> if <code>x</code> was not defined earlier.</p>

<p>This mistake gets worse with nested loops:</p>

<pre><code>for y in outer_iterator:
    # should have set default value for x here
    # but forgot
    for x in inner_iterator(y):
        # do stuff
    # do something with x
</code></pre>

<p>Here forgetting the <code>x = default_value</code> results in a silent error instead of an exception if <code>inner_iterator(y)</code> is empty on the second or later iteration through the outer loop.</p>

<p>Testing these situations is tough, because <code>inner_iterator(y)</code> is not an outside argument, so unless the test is lucky enough to somehow recreate the case when it's empty, the bug won't be detected.</p>

<p>Are all use cases fragile or is there a safe way to rely on the scoping rule of the for-loop variables? </p>

<p>There is no 100% safe way to rely on a variable being set inside a for-loop unless you can be 100% sure that the iterator is never empty. To achieve the 100% assurance, you could do something like <code>for x in iterator or [None]:</code>, but this poses a similar "remembering to do it" problem. It is probably more "pythonic" than setting defaults, but defaults may provide more clarity. The whole relying on for-loop scoping is similar to something like <code>if (condition): x = something</code> and then contemplating about what if I call x when condition is false? You probably would not write code like that anyway so why do it for for-loops? I like to make it a habit of declaring all variables that will be used outside upfront (e.g., setting all variables to None or some other default at the beginning of a function), but it just comes down to preference.</p>

python python-3.x scope