graph TD
A((Start)) --> IN[/Score/]
IN --> B{"Is<br>90 <= Score <= 100?"}
B -- Yes --> C[/A/]
B -- No --> D{"Is<br>Score >= 80?"}
D -- Yes --> E[/B/]
D -- No --> F{"Is<br>Score >= 70?"}
F -- Yes --> G[/C/]
F -- No --> H[/D/]
C --> I((End))
E --> I
G --> I
H --> I
15 Conditionals
“The best thing about a boolean is even if you are wrong, you are only off by a bit.” — Anonymous.
In programming, conditionals are used to make decisions based on certain conditions. They allow you to control the flow of your program by executing different blocks of code based on whether a condition is True or False. The “off by a bit” reference in the quote above is a nod to the binary nature of boolean values, which can only be True (1) or False (0).
Conditional statements allow control flow in a program, enabling it to perform different actions or execute specific blocks of code based on the evaluation of a condition.
15.1 Rule-Based Decision Making
In real-world scenarios, decision-making often involves a series of rules or conditions that guide the process. For example, consider a grading system based on the score of a student. The decision tree in Figure 15.1 shows how a student’s score can be used to determine their grade.
Notice that the decision tree branches based on the score of the student. If the score is greater than or equal to 90 and less than or equal to 100, the student receives an "A". If the score is between 80 and 89, the student receives a "B", and so on. The decision tree represents a rule-based system that maps input (the student’s score) to an output (the grade).
Rule-based systems is a common approach in programming to represent domain-specific knowledge or logic. The rules are typically expressed as conditional statements that guide the program’s behavior. It is often referred to as the first level of artificial intelligence (AI) and is used in expert systems, chatbots, and other applications.
15.2 Conditional Statements in Python
In Python, conditionals are expressed using:
ifstatementsif…elsestatementsif…elif…elsestatementsmatchstatements (introduced in Python 3.10)
Statements are pieces of code that are executed whereas expressions are pieces of code that are evaluated to produce a value. Therefore, statements will perform an action (e.g., assigning a value to a variable, checking a condition, looping, or defining a function) and will often comprise multiple expressions.
15.3 if Statements
An if statement is used to conditionally execute a block of code. The code block is executed only if the condition specified in the if statement is True. The syntax of an if statement is as follows:
The code block inside the if statement is indented to indicate that it is part of the if block. If the condition is True, the code block is executed; otherwise, it is skipped.
For example:
In this example, the code inside the if block will only execute if the condition x > 5 is True.
Example - Letter Grade (if). In Listing 15.1, we define a function that returns "A", "B", "C", or "D" if a score falls within the following numerical ranges:
- If score is between 90 and 100, return
"A". - If score is between 80 and 89, return
"B". - If score is between 70 and 79, return
"C". - If score is between 0 and 69, return
"D".
if statement to convert a score to a letter grade. In Listing 15.1 (a), we use the and operator to check multiple conditions. In Listing 15.1 (b), we use chain comparisons to simplify the code. Chain comparisons are a concise way to check if a variable is within a range.
How could we test the function letter_grade? In Listing 15.1, we define a test function that checks if the function returns the correct grade for a given score. We are particularly interested in the boundaries between grades.
letter_grade function to check if it returns the correct grade for a given score. The boundaries (i.e., the points where the grade changes) are typically the most critical points to test because they are more likely to contain bugs.
def test_letter_grade():
assert letter_grade(90) == "A"
assert letter_grade(91) == "A"
assert letter_grade(89) == "B"
assert letter_grade(81) == "B"
assert letter_grade(80) == "B"
assert letter_grade(79) == "C"
assert letter_grade(71) == "C"
assert letter_grade(70) == "C"
assert letter_grade(69) == "D"
assert letter_grade(0) == "D" 🤔 The
letter_gradein Listing 15.1 is not perfect. What happens if the score is negative?
15.4 if-else Statement (Two-Way if)
An if-else statement allows us to handle two cases based on a condition. If the condition is True, one block of code is executed; otherwise, another. The syntax of an if-else statement is as follows:
Example - Greater or Not. In Listing 15.3, we define a function that prints a message based on the value of x and y. If x is greater than y, the message "{x} is greater than {y}" will be printed. Otherwise, the message "{x} is not greater than {y}" will be printed.
if-else statement.
5 is greater than 3
3 is not greater than 5
Example - Even or Odd. In Listing 15.4, we define a function that returns "Even" if the number is even and "Odd" if it’s odd.
if-else statement. Only one block within the conditions will trigger.
Sometimes, the else block can be omitted in the function body. In Listing 15.5, we define a function that checks if a number is even or odd using an if statement without the else block. If the condition is True, the return statement is executed, and the function exits. If the condition is False, the function continues to the next statement after the if block.
if-else statement without the else block. Only one block within the conditions will trigger.
In Listing 15.6, we review the letter_grade function and add a condition to handle invalid grades (i.e., scores less than 0 or greater than 100). We return None for invalid grades.
if-else statement. The function returns None for invalid grades.
15.5 Nested if Statements
Nested if statements allow us to check multiple conditions by nesting one if within another. It provides a way to handle more complex decision trees. The syntax of a nested if statement is as follows:
if condition1:
if condition2:
# Block 1 (condition1 and condition2 are True)
else:
# Block 2 (condition1 is True and condition2 is False)
else:
if condition2:
# Block 3 (condition1 is False and condition2 is True)
else:
# Block 4 (condition1 and condition2 are False)
# Code block outside the nested if statementNotice that the same structure could be alternatively represented as:
if condition1 and condition2:
# Block 1 (condition1 and condition2 are True)
if condition1 and not condition2:
# Block 2 (condition1 is True and condition2 is False)
if not condition1 and condition2:
# Block 3 (condition1 is False and condition2 is True)
if not condition1 and not condition2:
# Block 4 (condition1 and condition2 are False)
# Code block outside the nested if statementExample - Interval Formatting. In Listing 15.7, we define a function that formats an interval based on the start and end values and whether the interval is inclusive or exclusive. The function returns the formatted interval as a string.
if statements.
def format_interval(
start_value,
end_value,
is_start_inclusive=True,
is_end_inclusive=True
):
if start_value > end_value:
return "Error: Invalid Range"
if is_start_inclusive:
if is_end_inclusive:
return f"[{start_value}, {end_value}]"
else:
return f"[{start_value}, {end_value})"
else:
if is_end_inclusive:
return f"({start_value}, {end_value}]"
else:
return f"({start_value}, {end_value})"
# Assertions for validation
assert format_interval(1, 5) == "[1, 5]"
assert format_interval(1, 5, is_start_inclusive=False) == "(1, 5]"
assert format_interval(1, 5, is_end_inclusive=False) == "[1, 5)"
assert format_interval(
1, 5,
is_start_inclusive=False,
is_end_inclusive=False
) == "(1, 5)"
assert format_interval(5, 1) == "Error: Invalid Range"15.6 if-elif-else Statement (Multi-Way if)
The if-elif-else statement allows us to check multiple conditions sequentially and execute the first one that evaluates to True. It’s useful for handling multiple cases. The elif stands for “else if.”
The syntax of an if-elif-else statement is as follows:
Example - Letter Grade (if-elif-else). In Listing 15.8, we review the letter_grade function and rewrite it using an if-elif-else statement.
if-elif-else statement. Only one block within the conditions will trigger.
def letter_grade(score):
if score < 0 or score > 100:
return "Invalid Grade"
elif score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "D"
assert letter_grade(95) == "A"
assert letter_grade(85) == "B"
assert letter_grade(75) == "C"
assert letter_grade(65) == "D"
assert letter_grade(-5) == "Invalid Grade"
assert letter_grade(105) == "Invalid Grade"15.7 match Statement
Python 3.10 introduced the match statement, which can be used to perform pattern matching. It allows you to match a value against a series of patterns and execute the corresponding block of code. Sometimes, it can be more concise and readable than using if-elif-else statements. The syntax is shown in Listing 15.9.
match statement in Python. The case _: is the default case that executes when no other pattern matches. Only one block within the conditions will trigger. The cases are evaluated in order, and the first matching case is executed.
A pattern can be:
- A literal value (e.g.,
1,"apple") - A variable (e.g.,
x,name) - A wildcard (
_) to match any value - A sequence of patterns (e.g.,
(1, 2)) - A combination of literals (e.g.,
1 | 2)
See the Python documentation for more details on the match statement.
Example - Week Day. In Listing 15.10, we define a function that returns the name of the day of the week based on the day number.
match statement. Only one block within the conditions will trigger.
def week_day(day):
match day:
case 1: return "Monday"
case 2: return "Tuesday"
case 3: return "Wednesday"
case 4: return "Thursday"
case 5: return "Friday"
case 6: return "Saturday"
case 7: return "Sunday"
case _: return "Invalid Day"
# Validation
assert week_day(1) == "Monday"
assert week_day(4) == "Thursday"
assert week_day(7) == "Sunday"
assert week_day(0) == "Invalid Day"Example - Categorizing Cars. In Listing 15.11, we define a function that categorizes a car into one of four categories based on whether it’s electric and sporty. The function takes two Boolean parameters, is_electric and is_sporty, and returns the car category:
"Electric Sportscar":is_electricisTrueandis_sportyisTrue"Electric Car":is_electricisTrueandis_sportyisFalse"Sportscar":is_electricisFalseandis_sportyisTrue"Regular Car":is_electricisFalseandis_sportyisFalse
match statement.
def categorize_car(is_electric, is_sporty):
match (is_electric, is_sporty):
case (True, True): return "Electric Sportscar"
case (True, False): return "Electric Car"
case (False, True): return "Sportscar"
case (False, False): return "Regular Car"
case _: return "Invalid Input"
# Validation
assert categorize_car(True, True) == "Electric Sportscar"
assert categorize_car(True, False) == "Electric Car"
assert categorize_car(False, True) == "Sportscar"
assert categorize_car(False, False) == "Regular Car"Example - Month to Quarter. In Listing 15.12, we define a function that converts a month number to the corresponding quarter of the year. We use | (named “pipe”) to combine multiple values in a pattern. The pipe operator in programming is usually used to denote a logical OR operation.
match statement.
def month_to_quarter(month):
match month:
case 1 | 2 | 3: return "Q1"
case 4 | 5 | 6: return "Q2"
case 7 | 8 | 9: return "Q3"
case 10 | 11 | 12: return "Q4"
case _: return "Invalid Month"
# Validation
assert month_to_quarter(1) == "Q1"
assert month_to_quarter(4) == "Q2"
assert month_to_quarter(7) == "Q3"
assert month_to_quarter(10) == "Q4"
assert month_to_quarter(13) == "Invalid Month"15.8 Truthy and Falsy Values
In Python, values can be evaluated in a boolean context. This means that they can be used as conditions in if statements.
Truthy Values. Values that evaluate to True in a boolean context are called truthy values. For example:
True- Any non-zero number
- Any non-empty string
- Any non-empty collection (list, tuple, dictionary, set)
Falsy Values. Values that evaluate to False in a boolean context are called falsy values. For example:
FalseNone0,0.0,0j(zero as an integer, float, or complex number)""(empty string)[],(),{},set()(empty list, tuple, dictionary, set)
Example - Checking if a List is Empty. In Listing 15.13, we define a function that checks if a list is empty using the list itself in an if statement.
if statement.
Example - Checking if a String is Empty. In Listing 15.14, we define a function that checks if a string is empty using the string itself in an if statement.
if statement.
Example - Checking if a Number is Non-Zero. In Listing 15.15, we define a function that checks if a number is non-zero using the number itself in an if statement.
if statement.
Notice that throughot Listing 15.13, Listing 15.14, and Listing 15.15, the if statement evaluates the value in a boolean context, without the need to compare it to True or False. Comparing a value to True or False is redundant and not Pythonic as illustrated in Figure 15.2.
True or False in an if statement. Python evaluates the value in a boolean context.
15.9 Conditional Expressions (Ternary Operator)
Python supports a concise way to write conditional expressions using the ternary operator (also known as a conditional expression). The syntax of a ternary operator is as follows:
The ternary operator is a one-liner that allows you to evaluate a condition and return one of two values based on the result. It’s a compact way to write simple if-else statements.
Example - Absolute Value. In Listing 15.16, we define a function that calculates the absolute value of a number using the ternary operator.
Example - Maximum of Two Numbers. In Listing 15.17, we define a function that returns the maximum of two numbers using the ternary operator.
15.10 Short-Circuit Evaluation
In Python, logical operators (and, or) use short-circuit evaluation. This means that the evaluation of the expression stops as soon as the result is determined (see the docs).
15.10.1 Short-Circuiting with and
When using the and operator:
- If the first expression is
False, the result isFalse, and the second, third, etc., expressions are not evaluated. - If the first expression is
True, the result depends on the second expression. If the second expression isTrue, the result depends on the third expression, and so on.
Example - Short-Circuiting with and. In Listing 15.18, we define a function that calls another function only if the input is not None.
and operator. The is_valid function is only called if the password is not None.
def is_valid(password: str) -> bool:
"""Check if the password is valid.
A valid password must:
- Be at least 8 characters long
- Not be all lowercase or all uppercase
Parameters:
----------
password (str): The password to check.
Returns:
-------
bool: True if the password is valid, False otherwise.
"""
print(f"Checking password {password}. ", end="")
return (
len(password) >= 8
and password.lower() != password
and password.upper() != password
)
def check_password(password):
if password and is_valid(password):
print("Password is valid!")
else:
print("Invalid password!")
# Test the function
check_password("Password123")
check_password("password")
check_password(None)
check_password("")Checking password Password123. Password is valid!
Checking password password. Invalid password!
Invalid password!
Invalid password!
15.10.2 Short-Circuiting with or
When using the or operator:
- If the first expression is
True, the result isTrue, and the second, third, etc., expressions are not evaluated. - If the first expression is
False, the result depends on the second expression. If the second expression isFalse, the result depends on the third expression, and so on.
Example - Short-Circuiting with or. In Listing 15.19, we define a function that evaluated the results of three expensive functions and returns True if any of them is True.
or operator. The functions f1, f2, and f3 are only evaluated as needed, that is, until the first True result is found.
from time import sleep, time
def f1(num):
print("Evaluating f1.")
sleep(1)
return num % 2 == 0
def f2(num):
print("Evaluating f2.")
sleep(1)
return num % 2 == 0
def f3(num):
print("Evaluating f3.")
sleep(1)
return num % 2 == 0
def check_any_condition(n1, n2, n3):
return f1(n1) or f2(n2) or f3(n3)
# Measure the time taken to evaluate the function
print("Only the first function should be evaluated.")
start_time = time()
check_any_condition(2, 2, 1)
end_time = time()
print(f"Time taken: {end_time - start_time:.2f} seconds")
print("Only the first two functions should be evaluated.")
start_time = time()
check_any_condition(1, 2, 2)
end_time = time()
print(f"Time taken: {end_time - start_time:.2f} seconds")
print("All functions should be evaluated.")
start_time = time()
check_any_condition(1, 1, 1)
end_time = time()
print(f"Time taken: {end_time - start_time:.2f} seconds")Only the first function should be evaluated.
Evaluating f1.
Time taken: 1.00 seconds
Only the first two functions should be evaluated.
Evaluating f1.
Evaluating f2.
Time taken: 2.00 seconds
All functions should be evaluated.
Evaluating f1.
Evaluating f2.
Evaluating f3.
Time taken: 3.00 seconds
🤔 What are the states of the call stack when executing Listing 15.19?
15.11 Conditional Statements for Error Handling?
In Python, conditional statements can be used for error handling. For example, you can check if a file exists before reading it, or if a value is None before using it. However, Python provides a more robust way to handle errors using exceptions. Exceptions are a way to handle errors that occur during the execution of a program. They allow you to gracefully handle errors and exceptions that may arise during the execution of your code.
In Listing 15.20, we compare two ways to handle a division by zero error. The first function uses an if statement to check if the denominator is zero before performing the division. The second function uses a try-except block to catch the ZeroDivisionError exception that occurs when dividing by zero.
if statement and a try-except block.
if statement to check if the denominator is zero before performing the division.
ZeroDivisionError exception using a try-except block. When an exception occurs, the code inside the except block is executed.
In general, it’s recommended to use exceptions for error handling in Python since they provide a more robust and flexible way to handle errors. Exceptions allow you to separate error-handling code from the normal flow of your program, making your code cleaner and easier to read. In Listing 15.20, the try-except block can be further extended to handle other exceptions that may occur during the division operation, for example, TypeError if the input is not a number. For example, in Listing 15.21, we extend the divide_v2 function to handle both ZeroDivisionError and TypeError exceptions.
divide_v2 function to handle both ZeroDivisionError and TypeError exceptions using a try-except block.
def divide_v2(
numerator,
denominator
):
try:
return numerator / denominator
except ZeroDivisionError:
print("Cannot divide by zero.")
return None
except TypeError:
print("Invalid input type.")
return None
except ValueError:
print("Invalid value.")
return None
# Test the function
assert divide_v2(10, 2) == 5
assert divide_v2(10, 0) == None
assert divide_v2(10, "2") == None
# Test division by infinity
import math
assert divide_v2(10, math.inf) == 0
# Test division by very small number (close to zero)
assert divide_v2(10, 1e-1000) == NoneCannot divide by zero.
Invalid input type.
Cannot divide by zero.
15.12 Isn’t AI Just a Bunch of if-else Statements?
On the surface, artificial intelligence (AI) may seem like a series of nested if-else statements: given input data, an AI model will output a certain prediction or decision. The big diffence is on how the output is generated. In the case of if-else statements, the logic is explicitly defined by the programmer. The domain knowledge is encoded in the form of conditions and rules, and the program follows these rules to make decisions.
As for AI models, they can handle more complex logic by learning the conditions from large amounts of data. This is done through a process called machine learning, where the model learns patterns and relationships in the data to make predictions or decisions. It would be extremely difficult, for example, creating a decision tree for driving autonomous cars using nested if-else statements due to the complexity and large scope of the rules. Using AI, the model can learn from examples of driving behavior and road conditions to make decisions in real-time.
15.13 Exercises
15.13.1 Is Even
Write a Python function that takes an integer as input and returns True if the number is even and False otherwise. Use only if statements.
15.13.2 Categorize Number
Write a Python function that takes an integer as input and returns:
"Positive"if it’s positive,"Negative"if it’s negative, and"Zero"if it’s zero,
using only if statements.
15.13.3 Determining Quadrant
Write a function that takes two numbers (x and y) as input representing coordinates on a 2D plane. The function should return the quadrant in which the point lies ("Quadrant I", "Quadrant II", "Quadrant III", or "Quadrant IV") or "Origin" if the point is at the origin (0, 0). Use only if statements without else.
def determine_quadrant(x, y):
pass # Add code here!
def test_determine_quadrant():
assert determine_quadrant(3, 4) == "Quadrant I"
assert determine_quadrant(-3, 4) == "Quadrant II"
assert determine_quadrant(-3, -4) == "Quadrant III"
assert determine_quadrant(3, -4) == "Quadrant IV"
assert determine_quadrant(0, 0) == "Origin"15.13.4 Vowel or Consonant
Write a function that takes a single character (a letter) as input and returns "Vowel" if it’s a vowel, namely, "a", "e", "i", "o", or "u", or "Consonant" otherwise. Create a version of the function using all Python’s conditional statements:
ifif-elseif-elif-elsematch- Ternary operator
15.13.5 Checking Divisibility
Write a Python function that takes two integers as input and returns "Divisible" if the first number is divisible by the second number, and "Not Divisible" otherwise.
15.13.6 Checking Age Eligibility
Write a Python function that takes an age as input and returns "Eligible" if the age is 18 or older, and "Not Eligible" otherwise.
15.13.7 Checking Valid Username
Write a Python function that takes a username as input and returns "Valid" if the username contains at least 6 characters and does not contain spaces, and "Invalid" otherwise.
15.13.8 Categorizing BMI
Create a function that categorizes a person’s Body Mass Index (BMI) into "Underweight", "Normal", "Overweight", or "Obese". The criteria is as follows:
- Underweight: BMI < 18.5
- Normal: 18.5 <= BMI <= 24.9
- Overweight: 25 <= BMI <= 29.9
- Obese: BMI >= 30
- Invalid BMI: BMI < 0
def categorize_bmi(bmi:float) -> str:
"""Categorize BMI:
Criteria:
--------
- Underweight: BMI < 18.5
- Normal: 18.5 <= BMI <= 24.9
- Overweight: 25 <= BMI <= 29.9
- Obese: BMI >= 30
- Invalid BMI: BMI < 0
Parameters:
----------
- bmi: int
Value of BMI
Return:
-------
- Category: str
Category of the BMI
"""
if bmi < 0:
return "Invalid BMI"
if bmi < 18.5:
return "Underweight"
if bmi <= 24.9:
return "Normal"
if bmi <= 29.9:
return "Overweight"
if bmi >= 30:
return "Obese"
# If one triggers, the flow jumps to here
return response
assert categorize_bmi(22.5) == "Normal"
assert categorize_bmi(29) == "Overweight"
assert categorize_bmi(31.7) == "Obese"
assert categorize_bmi(-5) == "Invalid BMI"15.13.9 Number Sign
Write a function that takes two integers as input and returns "Positive" if both are positive, "Negative" if both are negative, and "Mixed" otherwise.
15.13.10 Increasing / Decreasing Order
Write a function that takes three numbers as input and returns "Increasing" if they are in increasing order, "Decreasing" if they are in decreasing order, and "Neither" otherwise.
15.13.11 Triangle Type
Write a function that takes three integers as input representing the sides of a triangle and returns "Equilateral" if all sides are equal, "Isosceles" if two sides are equal, and "Scalene" if all sides are different.
15.13.12 Checking Leap Year
Write a function that takes a year as input and returns "Leap Year" if it’s a leap year and "Not a Leap Year" if it’s not.
15.13.13 Checking Validity of a Date
Write a function that takes three integers as input representing a date (day, month, year) and returns
"Valid"if the date is valid, or"Invalid", otherwise.
Make sure you consider leap years!
def check_date_validity(day, month, year):
# Check if year is valid
# Check if month is valid
# If month has 30 days, check if day <= 30
# If month has 31 days, check if day <= 31
# If month is Feb and the year is a leap year, day <=29
# If month is Feb and the year is not a leap year, day <=28
def test_check_date_validity():
assert check_date_validity(31, 12, 2023) == "Valid"
assert check_date_validity(29, 2, 2024) == "Valid"
assert check_date_validity(30, 2, 2024) == "Invalid"
# Add more edge cases here!15.13.14 Multiple Conditions with Strings
Write a function that takes two strings as input and returns "Equal" if they are the same, "Different" if they are different, and "CaseSensitive" if they are different considering case.
15.13.15 Checking Password Validity
Write a function that takes a password as input and returns "Valid" if the password meets the following criteria:
- Contains at least one uppercase letter.
- Contains at least one lowercase letter.
- Contains at least one numeric digit.
- Contains at least one special character
(!@#$%^&*()_+[]{}|;:'",.<>?). - Has a minimum length of 8 characters.
Return "Invalid" if any of these criteria are not met.
def check_password_validity(password):
pass # Add code here!
def test_check_password_validity():
assert check_password_validity("Password123!") == "Valid"
assert check_password_validity("WeakPass") == "Invalid"
assert check_password_validity("SecurePass123") == "Invalid"
assert check_password_validity("Complex@Pswd123") == "Valid"def check_password_validity(password:str)->str:
"""Check is password is valid.
Criteria
--------
- Contains at least one uppercase letter.
- Contains at least one lowercase letter.
- Has a minimum length of 8 characters.
- Contains at least one special character (!@#$%^&*()_+[]{}|;:'",.<>?).
- Contains at least one numeric digit.
Parameters
----------
password : str
_description_
Returns
-------
str
Valid if password satisfies the criteria, Invalid otherwise
"""
# input: 2wWE
# output: 2WRAWE (upper)
if password.upper() == password:
return "Invalid"
# only upper letters
# Check if password has at least one uppercase letter
if password.islower():
return "Invalid"
if password.isupper():
return "Invalid"
if len(password) < 8:
return "Invalid"
if password.isalnum():
return "Invalid"
has_number = False
for s in password:
if s in "1234567890":
has_number = True
if not has_number:
return "Invalid"
has_letter = False
for s in password:
if s in "abcdefghijklmnopqrstuwxyz":
has_letter = True
if not has_letter:
return "Invalid"
return "Valid"
assert check_password_validity("password@#$3432") == "Invalid"
assert check_password_validity("PASSWORD@#$3432") == "Invalid"
assert check_password_validity("PASswORD@#$3432") == "Valid"
# Minimum 8
assert check_password_validity("123sS%") == "Invalid"
assert check_password_validity("123sS%78") == "Valid"
assert check_password_validity("123sS%789") == "Valid"
assert check_password_validity("123sS%7") == "Invalid"
assert check_password_validity("Password123!") == "Valid"
assert check_password_validity("SecurePass123") == "Invalid"
assert check_password_validity("Complex@Pswd123") == "Valid"
assert check_password_validity("WeakPass") == "Invalid"
assert check_password_validity("112312312313") == "Invalid"
assert check_password_validity("11231231231%$%3") == "Invalid"15.13.16 Checking Password Validity (Using Subfunctions)
Redo the function check_password_validity using the following subfunctions to test the criteria:
has_uppercase(password)has_lowercase(password)has_digit(password)has_special_char(password)has_min_length(password, min_length)
Also, write a test function with the edge cases for each subfunction and a test function for check_password_validity_clean.
def has_uppercase(password):
pass # Add code here!
def has_lowercase(password):
pass # Add code here!
def has_digit(password):
pass # Add code here!
def has_special_char(password):
pass # Add code here!
def has_min_length(password, min_length):
pass # Add code here!
def check_password_validity_clean(password):
pass # Add code here!
def test_subfunctions():
# Add test cases for each subfunction
def test_check_password_validity_clean():
# Add test cases for check_password_validity_clean15.13.17 Convert Letter Grade
Write a Python function that takes a numeric grade (0 to 100) as input and returns the corresponding letter grade ("A", "B", "C", "D", or "F") using if-elif-else statements.
The grading scale is as follows:
- If the grade is between 90 and 100, return
"A". - If the grade is between 80 and 89.9, return
"B". - If the grade is between 70 and 79.9, return
"C". - If the grade is between 60 and 69.9, return
"D". - If the grade is less than 60, return
"F".
If the grade is outside the range 0 to 100, return "Invalid Grade".
15.13.18 Categorizing Blood Pressure
Write a function that takes systolic and diastolic blood pressure readings as input and returns a category ("Normal", "Prehypertension", "Hypertension Stage 1", "Hypertension Stage 2", or "Hypertensive Crisis") using if-elif-else statements.
Blood Pressure Categories:
| Blood Pressure Category | Systolic Range | Diastolic Range |
|---|---|---|
| Normal | Below 120 | Below 80 |
| Prehypertension | 120–129 | Below 80 |
| Hypertension Stage 1 | 130–139 | 80–89 |
| Hypertension Stage 2 | 140 and above | 90 and above |
| Hypertensive Crisis | Above 180 | Above 120 |
def categorize_blood_pressure(systolic, diastolic):
pass # Add code here!
def test_categorize_blood_pressure():
assert categorize_blood_pressure(110, 70) == "Normal"
assert categorize_blood_pressure(125, 85) == "Invalid Blood Pressure"
assert categorize_blood_pressure(150, 95) == "Hypertension Stage 2"
assert categorize_blood_pressure(190, 130) == "Hypertensive Crisis"
assert categorize_blood_pressure(134, 85) == "Hypertension Stage 1"