Why do ‘and’ & ‘or’ return operands in Python?

I think you’re somehow confused about what the docs says. Take a look at these two docs sections: Truth Value Testing and Boolean Operators. To quote the last paragraph on the fist section:

Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)

As you can see, you’re right about operations and built-in functions but see the Important exception part, it is well stated that the Boolean operators will return one of their operands.

Now, what they can return depends hardly on the operator’s short circuit logic. For or operator, it will return the first truthy value in the expression, since when it finds one, the whole expression is true. In case of every operand being falsey, or will return the last operand, meaning that it iterated over every one of them not being able to find a truthy one.

For and operator, if the expression is true, it will return the last operand, if the expression is false, it will return the first falsey operand. You can read more about Short Circuit Evaluation at the Wikipedia Page.

You have a lot of examples in your question, let’s analyze some of them:

>>> False and 1  # return false (short circuited at first falsey value)
False
>>> True and 1   # return 1 (never short circuited and return the last truthy value)
1
>>> 1 and False  # return false (short circuited at first falsey value, in this case the last operand)
False
>>> 1 and True  # return True (never short circuited and return the last truthy value)
True
>>> True and 121  # return 121 (never short circuited and return the last truthy value)
121
>>> False or 1  # return 1 (since the first operand was falsey, or kept looking for a first truthy value which happened to be the last operator)
1
>>> False or 112  # return 112 for same reason as above
112
>>> False or "Khadijah"  # return "Khadijah" for same reason as above
'Khadijah'
>>> True and 'Khadijah'  # return "Khadijah" because same reason as second example
'Khadijah'

I think this should make a point. To help you further understand why this is useful, consider the following example:

You have a function that randomly generate names

import random

def generate_name():
    return random.choice(['John', 'Carl', 'Tiffany'])

and you have a variable that you don’t know if it has assigned a name yet so instead of doing:

if var is None:
    var = generate_name()

You can do oneliner:

var = var or generate_name()

Since None is a falsey value, or will continue its search and evaluate second operand, this is, call the function ultimately returning the generated name. This is a very silly example, I have seen better usages (although not in Python) of this kind of style. I couldn’t come out with a better example right now. You can also take a look at this questions, there are very useful answers on the topic: Does Python support short-circuiting?

Last but not least, this has nothing to do with static typed, duck typed, dynamic, interpreted, compiled, whatever language. It’s just a language feature, one that might come handy and that is very common since almost every programming language I can think of provide this feature.

Hope this helps!

Leave a Comment