1

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
Matt Key
  • 95
  • 1
  • 6
  • Where did you get the first syntax from? That's not how ternary conditions work in python. Your code is creating a tuple with `(a.val,0)`. That's the error. Use this instead `b = a.val if a is None else 0`. – Adithya Jan 08 '22 at 16:57
  • 1
    @Adithya it's an old trick from https://stackoverflow.com/a/470376/446792 and this is a case when it doesn't work – mx0 Jan 08 '22 at 17:01
  • Thanks.. Thought it's a trick. Didn't think newbies started with clever code. ;) – Adithya Jan 08 '22 at 17:11
  • 1
    the thing is that b is creating a tuple first then it does the `[a is None]` part... we know that a.val is undefined so it will result in an error. Check my answer for explanation! – Srishruthik Alle Jan 08 '22 at 23:04

1 Answers1

1

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!

Srishruthik Alle
  • 500
  • 3
  • 14
  • thanks @Srishruthik. But in the first one, shouldn't b resolve to 0 since the syntax is: ```(if_test_is_false, if_test_is_true [test]``` then it shouldn't evaluate a.val right? [https://book.pythontips.com/en/latest/ternary_operators.html](https://book.pythontips.com/en/latest/ternary_operators.html) – Matt Key Jan 08 '22 at 19:17
  • 1
    No, 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. – Srishruthik Alle Jan 08 '22 at 22:55
  • So basically `b = (a.val,0)[a is None)` is equalivent to `b = (a.val,0)` `b[a is None]`... in the first statement(`b = (a.val,0)` it gives u and error since it can't evaluate a.val Hope this makes sense! – Srishruthik Alle Jan 08 '22 at 22:58
  • ohhhh. ok,great. Thanks! – Matt Key Jan 09 '22 at 17:34