While building a parameterized decorator, I had not realized reassignments to passed in arguments within nested functions were not allowed in Python. Looking further, I realized this is also true for simple functions as well. I have reduced the demonstration to the following nested function:
def a(s):
    def b():
        def c():
#             nonlocal s                         # fix
            print(s)
#             while s:
#                 s -= 1                         # uncommenting raises UnboundLocalError 
            print(s)
            return None
        return c()
    return b()
a(3)
# 3
# 3
I would like the following desired output by adding the commented while loop:
a(3)
# 3
# 0
Next, uncommenting the two lines of the while loop gives the following error, which suggests that reassigning a value to s raises an error:
<ipython-input-37-7141eb599936> in c()
      3         def c():
      4 #             nonlocal s                 # fix
----> 5             print(s)
      6             while s:
      7                 s -= 1                   # uncommenting raises UnboundLocalError
UnboundLocalError: local variable 's' referenced before assignment
Finally, uncommenting nonlocal fixes this issue and gives the desired output as suggested by this post. 
Although the problem is solved, I would like to understand the source of the issue.  I noticed the traceback points to the first use of the parameterized argument s (e.g. print(s)), rather than pointing to the lines that actually cause the error (i.e. the while loop/assignment).  
I suspect that upon calling a function, Python first establishes assignments of the local scope.  Assignments then take higher precedence over or override inherited variables from the outer scopes.  Thus without an assignment to s, the outer s is used.  By contrast, with an assignment, s is redefined at the function call, and any reference before the initial assignment will raise an error.  Is this correct, or can someone explain what Python is actually doing? 
 
    