I think Python's rules about what constitutes a new scope are a touch inconsistent--or, as the Zen might put it, "practical".

First, simple statements never create their own scope.  That's easy.  Second, compound statements that create a new function, "def" and "lambda", always create a new scope.  "class" also creates a new scope, but that's intuitive--and if you understand the language you know that under the hood it's also creating a code object like "def" and "lambda" do.  Anyway, none of the other "compound" statements create scopes.   That's true even for compound statements that themselves make assignments, like "for", "with", and "except".  But you'll note they also don't create new code objects.  Finally, we note that modules always have their own scopes.  And again, if you understand the language, you know they're also implemented using code objects.

If that was the whole list, then the mental model would be super simple: code objects always create their own scopes, and nothing else does.

But then we get to generator expressions and list/dict/set comprehensions.  I think of those as doing an "assignment", but I have to remember the assignment "doesn't leak":

   x = 3
   y = list(x**2 for x in range(5))
   print(f"{x=}")

This code prints "x=3".

Why this exception to the rule?  IIRC from the discussions back when they were added, this one of those "it just seemed best at the time" things.  "for" was added to the language long before I got there, but it "leaking" its assignment was judged useful; if you broke out of the loop, you could continue to examine the last value from the loop.  But, the thinking went, you'd never want to examine the last value from a list generator, so it was more convenient if it behaved as if it had its own scope.



//arry/

p.s. Maybe I should be using the word "binding" instead of "assignment"?  If there's an important distinction between the two terms I don't know it.

On 11/17/20 1:55 AM, Mark Shannon wrote:
Hi,

I'm wondering why
```
x = "value"
try:
    1/0
except Exception as x:
    pass
```

does not restore "value" to x after
the `except` block.

There doesn't seem to be an explanation for this behavior in the docs or PEPs, that I can find. Nor does there seem to be any good technical reason for doing it this way.

Anyone know why, or is just one of those unintended consequences like `True == 1`?


Here's an example of restoring the value of the variable after the `except` block:

>>> def f(x):
...     try:
...         1/0
...     except Exception as x:
...         pass
...     return x
...
>>> f("hi")
'hi'


Cheers,
Mark.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/KGYRLITEPB22ZZO4N7DD4A7QP7FQS6JO/
Code of Conduct: http://python.org/psf/codeofconduct/


_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/AZR3EUV4E5SV5J6GDSI5G5EG56CRM3BM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to