On Tue, Nov 17, 2020 at 09:55:46AM +0000, 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.
Because try, if, for, while, with etc. don't create a new scope. Only
two statements create a new scope: `def` and `class`.
I presume you don't also expect these to restore x after the
blocks are ended:
x = "value"
for x in range(100):
pass
with open('filename') as x:
text = x.read()
`try...except` is no different.
If you search the archives on Python-List, going back two or four years,
you will find extensive discussion between those who think that every
statement with an indent should create a new scope, and those who don't.
Apologies in advance to supporters of the "new scope" philosophy who
might feel I am giving the idea short shrift, but my recollection is
that they were unable to give any better justification than "but that's
what C does" and "well, it might be useful someday to use a name
inside a block without clobbering its existing value".
(My response to that is, just use a new variable name, it's not like
there is a shortage.)
The only wrinkle in the case of `try...except` is that the error
variable is deleted, even if it wasn't actually used. If you look at the
byte-code generated, each compound try...except with an exception
variable is followed by the equivalent of:
err = None
del err
There really ought to be a FAQ about this, but it has something to do
with the exception object forming a long-lasting reference cycle. To
avoid that, the error variable is nuked on leaving the compound block.
This is documented here:
https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
although only briefly and without much detail.
> Nor does there seem to be any good technical reason for doing it this
> way.
I expect the reason is the usual cost-benefit of "good enough". The
effort involved in storing the old name binding and then restoring it
afterwards is more than the benefit gained (almost zero).
This has been part of Python since Python 3.0, so if you are only just
noticing it, that gives an idea of how rarely it comes up.
> 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'
What Python interpreter are you using for that? This is not what happens
in Python 3:
# raises an exception
UnboundLocalError: local variable 'x' referenced before assignment
or Python 2.7:
# returns the exception object
ZeroDivisionError('integer division or modulo by zero',)
So unless you are using some modified or alternative interpreter, I
don't know how you got that output.
--
Steve
_______________________________________________
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/TIXX4P4KOA2OO7JTU3BCLNIGLIWC66M2/
Code of Conduct: http://python.org/psf/codeofconduct/