# Strange use of "and" / "or" operator

I'm trying to learn python and came across some code that is nice and short but doesn't totally make sense

the context was:

```
def fn(*args):
return len(args) and max(args)-min(args)
```

I get what it's doing, but why does python do this - ie return the value rather than True/False?

```
10 and 7-2
```

returns 5. Similarly, changing the and to or will result in a change in functionality. So

```
10 or 7 - 2
```

Would return 10.

Is this legit/reliable style, or are there any gotchas on this?

**TL;DR**

Logical **AND** (`and`

):

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

Logical **OR** (`or`

):

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

```
return len(args) and max(args) - min(args)
```

Is a *very* ~~pythonic~~ concise way of saying:

if

`args`

is not empty, return the result of`max(args) - min(args)`

.

The logical `and`

and `or`

operators are not restricted to working with, or returning boolean values. Any object with a truthiness value can be tested here. This includes `int`

, `str`

, `list`

, `dict`

, `tuple`

, `set`

, `NoneType`

, and user defined objects. Short circuiting rules still apply as well.

Note that this is a more concise way of constructing an `if-else`

expression:

```
return exp1 and exp2
```

Should (roughly) translate to:

```
r1 = exp1
if not r1:
return r1
return exp2
```

Here's some examples of how and where these constructs can be used to concisely handle invalid input.

**Example with**`and`

*(as shown by OP)*

`and`

*Return the difference between the min and max of a group of arguments.*

```
def foo(*args):
return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5)
4
foo()
0
```

Since `and`

is used, the second expression must also be evaluated if the first is `True`

. Note that, if the first expression is evaluated to be Truthy, the result returned is *always* the result of the *second expression*.

If the first expression is evaluated to be Falsey, then the result returned is the result of the first expression.

If `foo`

receives any arguments, `len(args)`

is greater than `0`

(a positive number), so the result returned is `max(args) - min(args)`

.

If `foo`

does not receive arguments, `len(args)`

is `0`

which is Falsey, and `0`

is returned.

Note that an alternative way to write this function would be:

```
def foo(*args):
if not len(args):
return 0
return max(args) - min(args)
```

**Example with**`or`

`or`

*Return all numbers over 9000.*

```
def foo(*args):
return [x for x in args if x > 9000] or 'No number over 9000!'
foo(9004, 1, 2, 500)
[9004]
foo(1, 2, 3, 4)
'No number over 9000!'
```

In this case `or`

is used. If the first expression is Truthy, then the result returned is the result of the first expression. Otherwise, both expressions are evaluated and the result returned is the result of the second expression.

`foo`

performs a filtration on the list to retain all numbers over `9000`

. If there exist any such numbers, the result of the list comprehension is a non-empty list which is Truthy, so it is returned (short circuiting in action here).

If there exist no such numbers, then the result of the list comp is `[]`

which is Falsey. So the second expression is now evaluated (a non-empty string) and is returned.

And the alternative for this function would be:

```
def foo(*args):
r = [x for x in args if x > 9000]
if not r:
return 'No number over 9000!'
return r
```

From: stackoverflow.com/q/47007680

**★ Back to homepage or read more recommendations:**