'python or statement, try, if, or getattr

I read a lot of articles about what it's better to check attribute and set default.

But all the people compare 'try', 'if' and 'getattr', but none use 'or'.

In this article, I found reason about performance, reflection, and typing. This is why I choose this article.

But it doesn't analize or compare with 'or', and I don't know why I don't see information about it. It is less pythonic? lost in performance? is less reliable?

example from the link

class Foo:
    def __init__(self, bar=None):
        self.bar = bar
class Bar:
    def __init__(self, baz):
        self.baz = baz
foo_with_bar = Foo(Bar(42))
foo_without_bar = Foo()

and to test the different options

def test_if(foo):
    baz = 'value_I_want'
    if foo.bar:
        baz = foo.bar.baz
    return baz

def test_ternary(foo):
    return foo.bar.baz if foo.bar else 'value_I_want'

def test_exception(foo):
    try:
        baz = foo.bar.baz
    except AttributeError:
        baz = 'value_I_want'
    return baz

def test_getattr(foor):
    return getattr(foo.bar, 'baz', 'value_I_want')

And here I whould like add one more option:

def test_or_statement(foo):
   retur foo.bar or 'value_I_want'

This 'or' statement is the one I can't see compared with the other, when it's better to use it, or avoid.



Solution 1:[1]

If you are talking about syntax like we see in javascript sometimes like an_object.a_falsy_value || a_default

const obj = {a:0}
console.log(obj.a || 2); // 2
console.log(obj.b || 2); // 2

this can't work always the same way in python:

class Obj:
    def __init__(self):
        self.a = 0

o = Obj()
print(o.a or 2) # 2
print(o.b or 2) # AttributeError: 'Obj' object has no attribute 'b'
print(getattr(o, 'b', 2)) # 2

Conclusion:

Using the or operator to provide a default value will work only for falsy values which are not undefined.

If you try to get an attribute or a dict key that doesn't exist you'll get AttributeError or KeyError.

So the safest way to provide default value for an attribute that could be not present at all is to use accordingly getattr(obj, attrname, default), or dict.get(key, default), etc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1