aleiphoenix <aleiphoe...@gmail.com> writes: > suppose following code running with Python-3.4.8 and Python-3.6.5 > > > # -*- coding: utf-8 -*- > > > def hello(): > err = None > print('0: {}'.format(locals())) > try: > b = 2 > print('1: {}'.format(locals())) > raise ValueError() > print('2: {}'.format(locals())) > except ValueError as err: > print('3: {}'.format(locals())) > pass > print('4: {}'.format(locals())) > return '', err > > > hello() > > > > got output: > > 0: {'err': None} > 1: {'err': None, 'b': 2} > 3: {'err': ValueError(), 'b': 2} > 4: {'b': 2} > Traceback (most recent call last): > File "err.py", line 19, in <module> > hello() > File "err.py", line 16, in hello > return '', err > UnboundLocalError: local variable 'err' referenced before assignment > > > But without this UnboundLocalError with Python-2.7.14 > > > My question is, does except ... as ... create a new scope from outer > block, causing 'err' be hidden from outer scope? Is this intentional?
Yes, it's intentional, but it's not exactly a scope. In https://docs.python.org/3/reference/compound_stmts.html#try you will find: When an exception has been assigned using as target, it is cleared at the end of the except clause. This is as if except E as N: foo was translated to except E as N: try: foo finally: del N This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs. This appears to be a change from Python 2. That wording is not present in https://docs.python.org/2/reference/compound_stmts.html#try -- Ben. -- https://mail.python.org/mailman/listinfo/python-list