pythonclassattributestry-catchnonetype

(Python) cant access attribute of an object unless I check nullity, why?


A LeetCode problem which is about linked lists that goes with this structure:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

Gave an error while attempting to print the val of the next node, but still worked when given a nullity check (it never even went to the else statement).

Assuming l1 is an instance of the class ListNode with print(l1.nextNode) gives: ListNode{val: 4, next: ListNode{val: 3, next: None}}

And: nextNode = l1.next

Why does this Fail: print(nextNode.val)

AttributeError: 'NoneType' object has no attribute 'val'

While this Works:

if nextNode is not None:
    print(nextNode.val)
else:
    print("Node is None")

Extra: I wonder if the answer to the above is related to why this also Fails with try/catch:

try:
    print("try block executed")
    print(nextNode.val)
except:
    **print("except block executed1")
    print(nextNode.val)**
    if nextNode is not None:
        print("except block executed"2)
        print(nextNode.val)
    else:
        print("Node is None")

While this Works and prints try block executed:

try:
    print("try block executed")
    print(nextNode.val)
except:
    if nextNode is not None:
        print("except block executed")
        print(nextNode.val)
    else:
        print("Node is None")

EDIT: Found the cause, turned out that the code fails for certain test case where it has only 1 node, but when it succeeds, it shows another test case result

Found this out while trying to create a copy-able code, rookie mistake...

For more details check the LeetCode problem in the link provided at the start.


Solution

  • When you reach the end of the list, nextNode will be None. None doesn't have a val attribute, so nextNode.val raises an exception.

    If you check whether it's None first, you don't execute that erroneous expression, so there's no error.

    When you use try/except, it catches the exception. But then in the except: block you try to print the same thing. It raises the exception again, and this time there's no try/except to catch it, so the program stops with an error.