How Do "And" and "Or" Act With Non-Boolean Values

How do and and or act with non-boolean values?

TL;DR

We start by summarising the two behaviour of the two logical operators and and or. These idioms will form the basis of our discussion below.

and

Return the first Falsy value if there are any, else return the last
value in the expression.

or

Return the first Truthy value if there are any, else return the last
value in the expression.

The behaviour is also summarised in the docs, especially in this table:























OperationResult
x or yif x is false, then y, else x
x and yif x is false, then x, else y
not xif x is false, then True, else False

How do 'and' and 'or' act with non-boolean values in Python?

This is the "and-or trick" -- and and or don't actually return boolean values; instead, they return one of their input arguments. People used to use this for control-flow.

As of python 2.5, it's not necessary anymore, because conditional expressions were introduced.

22 and 333/12 or 1

is equivalent to

333/12 if 22 else 1

Python: justification for boolean operators (and, or) not returning booleans

In Python's case, the bool type didn't even exist until over a decade after the language was released. If it had existed from the start, perhaps and and or would have been defined differently. But, as is, backward compatibility was far more important. From the PEP that introduced the type:

Another consequence of the compatibility requirement is that the expression "True and 6" has the value 6, and similarly the expression "False or None" has the value None. The "and" and "or" operators are usefully defined to return the first argument that determines the outcome, and this won't change; in particular, they don't force the outcome to be a bool. Of course, if both arguments are bools, the outcome is always a bool. It can also easily be coerced into being a bool by writing for example "bool(x and y)".

EDIT: BTW, at its start, Python was intended to "bridge the gap" between programming in "data-rich" languages like C and "convenient" languages like Unixy shells (sh, csh, etc). Python's and and or were more like && and || act in shell languages, consuming - left to right - all and only the operands needed to resolve whether the overall chain succeeded ("true") or failed ("false").

What does or mean inside a Python list comprehension?

Maybe this will make it easier for you to see:

actions.extend(self.get_action(action) for action in (self.actions or []))

The value of self.actions might have been None, i.e. it's type is an Optional[List[T]]

Using the or operator will return the first value that evaluates as true, or return the last value it evaluated. This uses short circuit logic, meaning if you have multiple values chained together, it will stop evaluating the expression once it finds the first "truthy" value (see bottom example).

For basic semantics, consider this example:

>>> a = None
>>> b = [1,2,3]
>>> c = a or b
>>> c
[1,2,3]

This is equivalent to:

a = None
b = [1,2,3]

if a:
c = a
else:
c = b

Some more examples:

>>> a = 1
>>> b = 2
>>> a or b
1

>>> a = 1
>>> b = None
>>> a or b
1

>>> a = None
>>> b = 2
>>> a or b
2

>>> a = None
>>> b = None
>>> a or b
None

>>> a = None
>>> b = False
>>> a or b
False

>>> a = 0
>>> b = 0
>>> c = 1
>>> a or b or c
1

Note in the last example we are able to chain multiple or calls together!

An example of short-circuiting (notice that foo(2) does not get called!):

>>> def foo(i):
... print(f"foo: {i}")
... return i
...
>>> foo(0) or foo(1) or foo(2)
foo: 0
foo: 1
1

Using logical operators in an expression

x and y is x if it is "false-y" (i.e. 0, False, None, [], '', ...), otherwise it is y.

x or y is x if it is "truth-y", otherwise it is y.

That is, x or y is the same as x if x else y, and x and y the same as x if not x else y.



Related Topics



Leave a reply



Submit