0

Consider the following function definition, where the exception name e shadows a parameter:

def f(a,e):
  try:
    raise RuntimeError('test')
  except RuntimeError as e:
    pass

In the symbol table of function f I would expect three symbols: two parameters a,e (not assigned) and one local e, which has been assigned. But the symbol table contains two symbols: parameter a, which has not been assigned, and parameter e, which has been assigned. It seems that the properties of the unassigned parameter e and the exception name e are combined into one symbol. Does that make sense?

See the following test code:

import symtable

def symStat(sym):
  stat = []
  if sym.is_parameter(): stat.append('param')
  if sym.is_assigned(): stat.append('assigned')
  if sym.is_referenced(): stat.append('referenced')
  return stat

INDENT_STR = '  '
def printSymsRec(st, indentLevel=0):
  indent = indentLevel*INDENT_STR
  print('%s%s:' % (indent, st.get_name()),
        [(sym.get_name(), symStat(sym)) for sym in st.get_symbols()])
  for stc in st.get_children():
    printSymsRec(stc, indentLevel+1)

TEST_CODE = """
def f(a,e):
  try:
    raise RuntimeError('test')
  except RuntimeError as e:
    pass
""".strip()

symRoot = symtable.symtable(TEST_CODE, "<string>", "exec")
printSymsRec(symRoot)

which gives the following output:

top: [('f', ['assigned'])]
  f: [('a', ['param']), ('e', ['param', 'assigned']), ('RuntimeError', ['referenced'])]

Why is the output not like the following:

...
  f: [('a', ['param']), ('e', ['param']), ('e', ['assigned']), ...]
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
coproc
  • 6,027
  • 2
  • 20
  • 31

1 Answers1

0

Parameters aren't special in this regard, they're just like any other name. So when except RuntimeError as e assigns to e, it overwrites the parameter's value. And this isn't specific to except statements; you can get the same behaviour from a simple assignment:

TEST_CODE = "def f(e): e = 0"
symRoot = symtable.symtable(TEST_CODE, "<string>", "exec")
printSymsRec(symRoot.get_children()[0])
# -> f: [('e', ['param', 'assigned'])]
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • Ok, I get it: `except ... as e` is - when looking at the name `e` - equivalent to `e = ...`. So the exception name `e` does not shadow the parameter, it remains a parameter. And additionally it gets a value assigned. – coproc Feb 09 '20 at 19:36
  • @coproc Yeah, exactly. I just added an example about that too. – wjandrea Feb 09 '20 at 19:42