Local variable 'j' referenced before assignment after "j in range(n)"


I have a question, unrelated to the whole program. The following program can work, but if I replace s_out += str(n-i) + s[n-1] with s_out += str(j+1-i) + s[j] , it won’t work. Why not? After a loop, j and (n-1) should be equivalent. I got an error “local variable ‘j’ referenced before assignment”.

class Solution38:
    def countAndSay(self, n: int) -> str:
        if n == 1:
            return '1'
        def rec_say(s): # recursive say
            n = len(s)
            i = 0
            s_out = ''
            for j in range(1,n):
                if s[j] != s[j-1]:
                    s_out +=  str(j-i) + s[i]
                    i = j
            # s_out += str(j+1-i) + s[j]  # j is actually (n-1) Why not work?
            s_out += str(n-i) + s[n-1]
            return s_out        

        s = '1'

        for i in range(n-1):
            s = rec_say(s)

        return s

sol38 = Solution38()

I thought it was because j was not predefined before range(n), but the following program does work:

for jx in range(3):
y1 = '1'
y1 += str(jx)

PS: I hate the usage of the class here, which does nothing. It is how Lxxxcode uses it, and I just copy it.

The loop variable will only exist if there is any looping:

>>> for i in range(0):
...    pass
>>> i
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'i' is not defined. Did you mean: 'id'?
>>> for i in range(1):
...    pass
>>> i

If the string is empty “” and n=0, the for loop doesn’t run and j never gets a value assigned at all.

Outside of a function, you get a NameError.

Inside a function, you get UnboundLocalError, which is a subclass of NameError.