Search code examples
pythontuplesternary

Python ternary object attribute evaluated out of order?


I'm relatively new to using Python and noticed something strange while Leetcoding the other day. I'm running this with Python 3.8 and get an object attribute error. But the attribute should not be accessed since the condition is true. Seems like this could have been answered already but I could not find a duplicate question. Could anyone help point me in the right direction with this? Thanks for your help.

#AttributeError: 'NoneType' object has no attribute 'val'
a = None
b = (a.val, 0)[a is None]
#works
a=None
if a is None:
    b=0
else:
    b=a.val

Solution

  • Ok so the reason why the 2nd one works is because a is set to None and it goes to the first if statement and skips the else statement since the first if statement is true. If u were to say like:

    a=None
    if a is not None:
        b=0
    else:
        b=a.val
    

    This would get an error: AttributeError: 'NoneType' object has no attribute 'val'.

    A Nonetype doesn't have a .val so I am not sure how you got that from?

    a = None
    print(a.val)
    

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

    Either way, if you want to have a ternary operator(btw ternary operator don't exist in python) so a similar way of doing this would be something like:

    (I am gonna assume that a.val is a class maybe?)

    a = None
    b = a.val if a is None else 0
    

    The reason why b = (a.val, 0)[a is None] gives you an error is cause

    if you think about it you are creating a tuple... So python first creates a tuple then does the [a is None] part. a.val is undefined so it will give you an error. If you try to do b = (a.val,0) (notice I remove the index part) it will give you the same error since first it creates a tuple.

    b = (a.val,0)[a is None) is equalivent to:

    b = (a.val,0)
    b[a is None]
    

    We know that a.val is undefined so it automatically gives you an attribute error.. so the index part isn't the error. It's your tuple part.

    Hope this makes sense!