Why does 'x or y' not return a Boolean value?

Viewed 183

Recently I have stumbled across an interesting piece of code in Python

condition and 'string1' or 'string2'

It took me some time to figure out its meaning but in the end it is another way to write a ternary expression

'string1' if condition else 'string2'

This made me realise x or y does not return True or False but x if x is True and y otherwise (Python Docs).

However, I don't see the reason why Python was designed that way. I've seen some use cases in checking for None

y = None
x = y or default

but this can be easily and clearer achieved using the following

x = y if y else default

Runtime-wise I also don't see the benefit since, if x is False, the second term in x or y needs to be evaluated at some point.

And in terms of code readability I would expect bool_test = x or y to contain a Boolean value.

So overall, why was Python designed in that way?

1 Answers

Strictly speaking, you are right, when we talk about logical operators - and and or, it should return a boolean - especially if you come from a strictly-typed language.

The thing is, dynamically typed (and often, scripted language) tend to have a wide range of truthiness, aka to evaluate the value of an expression if its TRUE or FALSE. One good example is that in MOST languages, evaluates zero, aka 0 as FALSE, and it is often implied that way.

Just that - in Python - there are whole lots of things that can be evaluated into FALSE, not just an integer of value 0. Empty lists, empty dictionaries, etc, often are implied as falsy aka if you do if [] -> its the same as if len(my_array)==0 which your length of array/lists is 0 and end up giving you a nice Boolean False.

You can take a look at the truthy table of python here

Value Truthiness
True ✅ TRUE
False ❌ FALSE
1 ✅ TRUE
0 ❌ FALSE
-1 ✅ TRUE
"True" ✅ TRUE
"False" ✅ TRUE
"1" ✅ TRUE
"0" ✅ TRUE
"-1" ✅ TRUE
"" ❌ FALSE
None ❌ FALSE
inf ✅ TRUE
-inf ✅ TRUE
[] ❌ FALSE
{} ❌ FALSE
[[]] ✅ TRUE
[0] ✅ TRUE
[1] ✅ TRUE

Readability wise - I think its subjective. x = y or default is definitely shorter than say, you know:

x = y if y is not None else default

because if it is implied that None will always be False, and, unless you have a very strong reason to argue that why None should not be falsy, then why do I bother writing if y is not None? (just evaluate it to False, skip it in the or comparator, and give me default, zoom zoom fast~)

Some people go for succinct code, and they claim it readable. Some like clear, affirmative syntax, like the verbose one, and claim it readable. So I guess that's where you choose your camp :)

Related