except blocks don't set up a new scope to me. [...second code example deleted...] says the same thing about the with statement to me.
(What version of Python are you using, a 2.6 build? In 2.5 release, a file() is not a context manager, so 'with file() as f:' doesn't work. And in py3k the "except E, N" syntax is gone.)
First off, you are absolutely right, the "with" and "except" statements do not open new scopes. I was wrong about that.
But PEP 3110, "Catching Exceptions In Python:, describes "except E as N" this way:
try: try_body except E as N: except_body ...
gets translated to (in Python 2.5 terms)
try: try_body except E, N: try: except_body finally: N = None del N ...
So the intent for "except E as N" is that N does *not* outlive the "except" block. And indeed that's what happens in my month-old Py3k.
Also, in your example "with file(...) as f:", outside the "with" block "f" evaluated as "<closed file 'C:/foo.txt', mode 'r' at 0x00B98800>". The file was closed because "with file(...) as f:" wasn't simply assigning the result of the "with" expression to f; it assigns to f the result of calling __enter__() on the with with expression's result. It seems that post-Python 2.5 file.__enter__() returns the file. This isn't a bad thing, but it's a little misleading as "with A as X" doesn't usually wind up with X containing the "result" of A.
So I can state: in Py3k, in both cases of "except E as N" and "with E as N", after the nested block has exited, N does not contain the direct result of E.
I guess I'm starting to disagree with sprinkling "as" into the syntax as the defacto inline assignment operator. Quoting from PEP 343:
So now the final hurdle was that the PEP 310 http://www.python.org/dev/peps/pep-0310 syntax:
with VAR = EXPR: BLOCK1
would be deceptive, since VAR does *not* receive the value of EXPR. Borrowing from PEP 340 http://www.python.org/dev/peps/pep-0340, it was an easy step to:
with EXPR as VAR: BLOCK1
Clearly the original intent with "as" was that it was specifically *not* direct assignment. Python added a *new keyword*, specifically because this was not direct inline assignment. So I assert a Python programmer should not see "as" and think "= with the two sides swapped".
For my final trick, I will attempt to channel Guido. (Which is spooky, as he hasn't even Crossed Over To The Other Side.) Python was originally written in C, the poster child for inline assignment operators, so he was obviously familiar with the syntactic construct. But Python does *not* support inline assignment everywhere. AFAIK it specifically has supports for it in one place: allowing multiple assignments at once. This works:
a = b = file(...)
But this does not:
if a = expression: # hooray, expression worked else: # boo, expression failed
Since nobody likes to type, I'm sure people have requested inline assignment zillions of times before. Since Python does not support it, I'm guessing Guido doesn't want it for some reason. Perhaps it's to save programmers from the inevitable heartache of typing "if a = x" when they meant "if a == x" (or vice-versa); if so then that's a little surprising, considering the "consenting adults" design tenet, but at least "if E as N" would not have that problem. If there was some other reason, then I bet "if E as N" doesn't address it.
Knock three times,