Python has three types of variable scopes:
- Globals: variables defined outside a function body
- local: variables defined within a function body
- nonlocal: variables defined within a nested function
The scope is determined by where the variable is assigned, not by where it is used (read).
Function huisu has an assignment of num, so the variable is considered local to function huisu i.e. the line:
num = num - 1
Since it has not previously been given a value, the error occurs.
Two solutions
Solution 1
Declare num as nonlocal
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        num = n             # Could assign num here
        def huisu(head):
            nonlocal num    # this declaration uses num in outer function
            if head == None:
                return
            else:
                before = head
                head = head.next
                huisu(head)
                if num == 0:
                    head.next = head.next.next
                else:
                    num = num - 1
                head = before
            return head
        
        num = n             # Or here, doesn't matter
                            # What matters is assigned before function call
        huisu(head)
Solution 2
Pass num as a parameter (more typical solution)
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        
        def huisu(head, num):  # pass num as 2nd argument
         
            if head == None:
                return
            else:
                before = head
                head = head.next
                huisu(head)
                if num == 0:
                    head.next = head.next.next
                else:
                    num = num - 1
                head = before
            return head
        
        huisu(head, n)