In Python we can do this:
if True or blah:
    print("it's ok") # will be executed
if blah or True: # will raise a NameError
    print("it's not ok")
class Blah:
    pass
blah = Blah()
if blah or blah.notexist:
    print("it's ok") # also will be executed
The or and and short circuit, see the Boolean operations documentation:
The expression
x and yfirst evaluatesx; ifxis false, its value is returned; otherwise,yis evaluated and the resulting value is returned.The expression
x or yfirst evaluatesx; ifxis true, its value is returned; otherwise,yis evaluated and the resulting value is returned.
Note how, for and, y is only evaluated if x evaluates to a True value. Inversely, for or, y is only evaluated if x evaluated to a False value.
For the first expression True or blah, this means that blah is never evaluated, since the first part is already True.
Furthermore, your custom Blah class is considered True:
In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false:
False,None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true. (See the__nonzero__()special method for a way to change this.)
Since your class does not implement a __nonzero__() method (nor a __len__ method), it is considered True as far as boolean expressions are concerned.
In the expression blah or blah.notexist, blah is thus true, and blah.notexist is never evaluated.
This feature is used quite regularly and effectively by experienced developers, most often to specify defaults:
some_setting = user_supplied_value or 'default literal'
object_test = is_it_defined and is_it_defined.some_attribute
Do be wary of chaining these and use a conditional expression instead where applicable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With