 # Control Flow & Truthiness

## Control Flow

I believe the main take away from this section is to briefly highlight the various control flows possible.

``````x = 5

if x % 2 == 0:
parity = "even"
else:
parity = "odd"

parity # 'odd'
``````

The author may, from time to time, opt to use a shorter ternary if-else one-liner, like so:

``````parity = "even" if x % 2 == 0 else "odd"
``````

The author points out that while while-loops exist:

``````x = 0

while x < 10:
print(f"{x} is less than 10")
x += 1
``````

for and in will be used more often (the code below is both shorter and more readable):

``````for x in range(10):
print(f"{x} is less than 10")
``````

We'll also note that `range(x)` also goes up to `x-1`.

Finally, more complex logic is possible, although we'll have to revisit exactly when more complex logic is used in a data science context.

``````for x in range(10):
if x == 3:
continue
if x == 5:
break
print(x)
``````

## Truthiness

Booleans in Python, `True` and `False`, are only have the first letter capitalized. And Python uses `None` to indicate a nonexistent value. We'll try to handle the exception below:

``````1 < 2 # True (not TRUE)
1 > 2 # False (not FALSE)

x = 1
try:
assert x is None
except AssertionError:
print("There was an AssertionError because x is not 'None'")
``````

A major takeaway for me is the concept of "truthy" and "falsy". The first thing to note is that anything after `if` implies "is true" which is why if-statements can be used to check is a list, string or dictionary is empty:

``````x = 
y = []

# if x...is true
# Truthy
if x:
print("Truthy")
else:
print("Falsy")

# if y...is true
# Falsy
print("Truthy") if y else print("Falsy")
``````

You'll note the ternary version here is slightly less readable. Here are more examples to understand "truthiness".

``````## Truthy example

# create a function that returns a string
def some_func():
return "a string"

# set s to some_func
s = some_func()

# use if-statement to check truthiness - returns 'a'
if s:
first_char = s
else:
first_char = ""

## Falsy example

# another function return empty string
def another_func():
return ""

# set another_func to y (falsy example)
y = another_func()

# when 'truthy' return second value,
# when 'falsy' return first value
first_character = y and y
``````

Finally, the author brings up all and any functions. The former returns `True` when every element is truthy; the latter returns `True` when at least one element is truthy:

``````
all([True, 1, {3}]) # True

all([True, 1, {}])  # False

any([True, 1, {}])  # True

all([])             # True

any([])             # False
``````

You'll note that the truthiness within the list is being evaluated. So `all([])` suggests there are no 'falsy' elements within the list, because it's empty, so it evaluates to `True`.

On the other hand, `any([])` suggests not even one (or at least one) element is 'truthy', because the list is empty, so it evaluates to `False`.

### Discussion   