5  Conditional

5.1 IF statement

5.1.0.1 if elif else Structure

temp = 15

if temp > 30:
  print("Too hot")
elif temp > 20:
  print("It's about right")
else:
  print("It's cold")
  
print("Bye!")
It's cold
Bye!

5.1.0.2 Ternary Operator

This is long

score = 4

if score >= 5:
  msg = "pass"
else:
  msg = "fail"

print(msg)
fail

use Ternary Operator instead

value_if_true if condition else value_if_false
score = 7

msg = "pass" if score >= 5 else "fail"
msg
'pass'

5.1.0.3 Logical Operators

and or not they can be short-circuited.

high_income = True
good_credit = False
student = False

if (high_income or good_credit) and not student:
  print("eligible")
else:
  print("not eligible")
eligible

5.1.0.4 Chaining Comparison Operators

age = 23

if 18 < age < 60:
  print("eligible")
eligible

5.2 match statement (Pattern matching)

Implemented in Python 3.10

5.2.1 Simple

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"
http_error(400)
http_error(418)
http_error(0)
"Something's wrong with the internet"

5.2.2 Combined

def http_error2(status):
    match status:
        case 400:
            return "Bad request"
        case 401 | 403 | 404: #  combine 
            return "Not allowed"
        case _:
            return "Something's wrong with the internet"
http_error2(401)
http_error2(403)
'Not allowed'
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def where_is(point):
    match point:
        case Point(x=0, y=0):
            print("Origin")
        case Point(x=0, y=y):
            print(f"Y={y}")
        case Point(x=x, y=0):
            print(f"X={x}")
        case Point():
            print("Somewhere else")
        case _:
            print("Not a point")
p0 = Point(0, 0)
where_is(p0)
Origin
p1 = Point(1, 1)
where_is(p1)
Somewhere else

5.2.3 Match By length

today_responses = [200, 300, 404, 500]
match today_responses:
    case [a]:
            print(f"One response today: {a}")
    case [a, b]:
            print(f"Two responses today: {a} and {b}")
    case [a, b, *rest]:
            print(f"All responses: {a}, {b}, {rest}")
All responses: 200, 300, [404, 500]

5.2.4 Using __match_args__

class Point:
    __match_args__ = ('x', 'y')
    def __init__(self, x, y):
        self.x = x
        self.y = y

# Suppose you have an instance of Point
point = Point(1, 2)

You can use pattern matching to destructure the point:

match point:
    case Point(x, y):
        print(f"The point is at ({x}, {y}).")
The point is at (1, 2).

Is equivalent to:

if isinstance(point, Point):
  print(f"The point is at ({point.x}, {point.y}).")
The point is at (1, 2).

In this example, the match statement checks if point is an instance of Point and then automatically unpacks its x and y attributes according to the order specified in __match_args__.

5.3 Execute based on argument type

def handle_float(x: float) -> None:
    print("x is float")

def handle_list(x: list) -> None:
    print("x is list")

def num_or_list(x: float | list) -> None:
    type_handler = {
        float: handle_float,
        list: handle_list,
    }
    handler = type_handler.get(type(x))
    if handler:
        handler(x)
    else:
        print("Unsupported type")
num_or_list(2.1)
x is float
num_or_list(["x", "y"])
x is list