In compiling a try statement, I see bytecodes like the following:
12 LOAD_NAME 1 (NameError)
14 CHECK_EXC_MATCH
16 POP_JUMP_FORWARD_IF_FALSE 22 (to 62)
18 STORE_NAME 2 (eg)
20 PUSH_NULL
22 LOAD_NAME 3 (bar)
24 LOAD_NAME 4 (f)
26 PRECALL 1
30 CALL 1
40 POP_TOP
42 POP_EXCEPT
44 LOAD_CONST 0 (None)
46 STORE_NAME 2 (eg)
48 DELETE_NAME 2 (eg)
50 LOAD_CONST 0 (None)
52 RETURN_VALUE
>> 54 LOAD_CONST 0 (None)
56 STORE_NAME 2 (eg)
58 DELETE_NAME 2 (eg)
60 RERAISE 1
The LOAD and STORE bytecodes are there only to prevent the DELETE from complaining about an unbound name.
The LOAD + STORE + DELETE can be replaced by a single (new) bytecode:
DELETE_NAME_NORAISE 2(eg)
This would remove four bytecodes from any ‘except[*] … as name’ clause.
I realize that a simple DELETE_NAME by itself would not work, because the handler might have deleted the variable. That’s why doing the LOAD + STORE is necessary.
Replacing the three bytecodes with a single DELETE_NAME_NORAISE would also work.
Likewise for DELETE_FAST_NORAISE, DELETE_DEREF_NORAISE, and DELETE_GLOBAL_NORAISE. Possibly also DELETE_SUBSCR_NORAISE and DELETE_ATTR_NORAISE, if there are other situations where a DELETE is compiled and it is not certain whether the subscript or attribute already exists.