0

Like so; the error is num is not defined

I want to use backtracking but how can I use a global variable in the funcation?

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        num = n
        def huisu(head):
            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)
王洲洋
  • 5
  • 2
  • 1
    You can simply put `num = n` _before_ the inner `def`. But the sane solution is to avoid global variables; pass it in as a second argument to the function. – tripleee Aug 29 '22 at 11:29
  • I have put num = n before the inner def. But I met a new Error: NameError name num is not defined, Did you mean sum? – 王洲洋 Aug 29 '22 at 11:34

3 Answers3

0

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)
DarrylG
  • 16,732
  • 2
  • 17
  • 23
  • Thank you so much, I have used Solution 1, and the console no longer reports errors. – 王洲洋 Aug 29 '22 at 12:34
  • @王洲洋 -- you're welcome. Personally, I prefer Solution 2 since globals and nonlocals are less favored when there is an easy alternative. This preference is not important for code snippets but makes large code bodies easier to maintain and read. – DarrylG Aug 29 '22 at 12:42
  • I know it's not good to use a declaration like nonlocal. But what can I do when I want to have a global variable in a nested function? I don't hope the value of num is influenced by value pass. – 王洲洋 Aug 29 '22 at 13:30
  • @王洲洋 -- no worries for your code snippet. Just pointing out that for larger code bases Solution #2 is better since it reduces coupling between the two functions. Examples of coupling for Solution #1 are 1) changes in num in the inner function with `num = num - 1` affecting the outer function. 2, you had to assign `num = n` in the outer function just to have a variable with the same name as the one in the inner function. If later you wanted to refactor variable num, you have to make sure it's done in both the inner and outer functions. – DarrylG Aug 29 '22 at 13:45
  • Solution 2 doesn't work here because the change to `num` is not reflected within the outer function, and thus changes are not reflected across the multiple recursive calls to the inner function. (Also, the recursive call needs to be modified to pass the parameter as well.) – Karl Knechtel Sep 13 '22 at 14:23
-1

num is out of scope. You have to define it before your inner function:

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        num = 0 # or some other default value
        def huisu(head):
            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
        huisu(head)
DSteman
  • 1,388
  • 2
  • 12
  • 25
-1

You are tring to evaluate something which is not declared before ... How can i know if num is equal to 0 if you didn't even declare it ?

Probably you missed a portion of function? By the way, the best solution is to declare it outside the def statment so the variable may be visible at the whole function.

Also remember to assign to it the correct value, num is in fact never used

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        
        def huisu(head):
            if head == None:
                return
            else:
                before = head
                head = head.next
                huisu(head)
                if num == 0: # here
                    head.next = head.next.next
                else:
                    num = num - 1
                head = before

            return head
        
        num = n
        huisu(head)

Did you mean:

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        num = n # Added
        def huisu(head):
            if head == None:
                return
            else:
                before = head
                head = head.next
                huisu(head)
                if num == 0: # here
                    head.next = head.next.next
                else:
                    num = num - 1
                head = before

            return head
        
        num = n
        huisu(head)
Zenek
  • 60
  • 2
  • 12