Short circuit of or and and , see documentation Logical operations :
The expression x and y first evaluates x ; if x false, its value is returned; otherwise y is evaluated and the return value is returned.
The expression x or y first evaluates x ; if x true, its value is returned; otherwise y is evaluated and the return value is returned.
Note that for and , y is evaluated only if x evaluates to True. Conversely, for or , y is evaluated only if x is evaluated as False.
For the first True or blah expression, this means that blah never evaluated, since the first part is already True .
In addition, your custom blah class is considered True:
In the context of Boolean operations, and also when expressions are used by flow control operators, the following values ββare interpreted as false: False , None , numeric zero of all types, and empty lines and containers (including strings, tuples, lists, dictionaries, sets, and freezes). All other values ββare interpreted as true. (See __nonzero__() special way to change this parameter.)
Since your class does not implement the __nonzero__() method (or the __len__ method), it is considered True with respect to Boolean expressions.
In the expression blah or blah.notexist , blah is thus true, and blah.notexist never evaluated.
This function is used quite regularly and effectively by experienced developers, most often specifying default values:
some_setting = user_supplied_value or 'default literal' object_test = is_it_defined and is_it_defined.some_attribute
Use caution when binding them and use a conditional expression instead, where applicable.