Previous | Tutorial index | Next
Correctly compose expressions using variables, data, operators, and the built-in functions of Python.
1.1 What is an Expression? (The Foundation)
An expression is any valid piece of code that Python can evaluate to produce a single value. It is the fundamental building block of programming.
5, "Hello", 3.14, Truex, total, name (variables that hold a value)3 + 4, x * 2, (a + b) / cx > 5, age == 18 (evaluate to True/False)age >= 18 and has_licenselen("hello"), type(10), str(42) (function calls are expressions!)len(products) * 2 + 5, int(age_str) + 1Why Expressions Matter: Every expression produces a value that can be:
total = 10 + 5if total > 10:print(10 + 5)Statements vs. Expressions (Crucial Distinction):
5 + 3x = 5 + 3 (an assignment statement that contains an expression on the right)if x > 0: contains the expression x > 0, but if itself is a statement.1.2 Operator Precedence (The Order of Operations)
Python follows a strict order when evaluating operators in a complex expression. Without this, 3 + 4 * 5 would be ambiguous. The precedence determines that multiplication happens before addition.
Full Precedence Table (from highest to lowest):
| Precedence Level | Operators | Description | Associativity |
|---|---|---|---|
| 1 (Highest) | (...), [...], {...} |
Parentheses, indexing, literals | Left-to-right |
| 2 | ** |
Exponentiation | Right-to-left |
| 3 | +x, -x, ~x |
Unary positive, negative, bitwise NOT | Right-to-left |
| 4 | *, /, //, % |
Multiplication, Division, Floor Division, Modulus | Left-to-right |
| 5 | +, - |
Addition, Subtraction | Left-to-right |
| 6 | <<, >> |
Bitwise shifts | Left-to-right |
| 7 | & |
Bitwise AND | Left-to-right |
| 8 | ^ |
Bitwise XOR | Left-to-right |
| 9 | | |
Bitwise OR | Left-to-right |
| 10 | ==, !=, >, <, >=, <=, is, is not, in, not in |
Comparisons, identity, membership | Left-to-right |
| 11 | not |
Logical NOT | Right-to-left |
| 12 | and |
Logical AND | Left-to-right |
| 13 (Lowest) | or |
Logical OR | Left-to-right |
Memorization Trick (PEMDAS/BODMAS with extensions):
not, and, or.The Associativity Trap (Exponentiation):
Most operators are left-associative (2 * 3 * 4 = (2*3)*4). However, exponentiation ** is right-associative:
2 ** 3 ** 2 is evaluated as 2 ** (3 ** 2) = 2 ** 9 = 512Best Practice: Use Parentheses! Always use parentheses to make your intention explicit, even when not strictly required:
result = (3 + 4) * 5 is clearer than result = 3 + 4 * 5result = (2 ** 3) ** 2 if you want 64; 2 ** (3 ** 2) if you want 512.1.3 Common Built-in Functions (Beyond print() and input())
Built-in functions are functions that are always available in Python without importing any modules. They are essential tools.
len(sequence): Returns the number of items in a sequence or collection.
len("Hello") → 5len([1, 2, 3]) → 3len((1, 2, 3, 4)) → 4len({"a": 1, "b": 2}) → 2 (returns number of key-value pairs)len() does not work on integers or floats (len(42) → TypeError).type(object): Returns the data type of the given object.
type(10) → <class 'int'>type(3.14) → <class 'float'>type("Hello") → <class 'str'>int(x): Converts x to an integer.
int("10") → 10int(3.99) → 3 (truncates towards zero, NOT rounding!)int("3.99") → ValueError (cannot convert a string with a decimal)float(x): Converts x to a floating-point number.
float("3.14") → 3.14float(5) → 5.0float("10") → 10.0str(x): Converts x to a string representation.
str(42) → "42"str(3.14) → "3.14"str(True) → "True""You have " + str(count) + " items"Additional Essential Built-ins (Beyond the Overview):
abs(x): Returns the absolute value of a number.
abs(-5) → 5abs(3.14) → 3.14round(x, ndigits): Rounds x to ndigits decimal places. If ndigits is omitted, rounds to the nearest integer.
round(3.14159, 2) → 3.14round(3.6) → 4round(2.5) → 2 (rounds to nearest even number to avoid bias in statistics). round(3.5) → 4.sum(iterable): Sums the elements of a list/tuple (must be numeric).
sum([1, 2, 3]) → 6sum((10, 20, 30)) → 60max(iterable) / max(a, b, c, ...): Returns the largest item.
max([3, 7, 2, 9]) → 9max(5, 8, 1, 10) → 10min(iterable) / min(a, b, c, ...): Returns the smallest item.
min([3, 7, 2, 9]) → 2pow(x, y): Equivalent to x ** y. Returns x raised to power y.
pow(2, 3) → 8sorted(iterable): Returns a sorted list from the given iterable (does not modify the original).
sorted([3, 1, 4, 2]) → [1, 2, 3, 4]String Methods (Often Used with len()):
text.upper() → returns uppercase versiontext.lower() → returns lowercase versiontext.strip() → removes leading/trailing whitespacetext.count(substring) → counts occurrences of a substringlen(" Hello ".strip()) → 51.4 Type Casting (Explicit Conversion)
Sometimes Python cannot automatically convert types (e.g., "10" + 5 → TypeError). You must explicitly cast.
Rules to Remember:
int("10.5") → ValueError (Use float("10.5") first, then int()).int("abc") → ValueErrorfloat("1e3") → 1000.0 (scientific notation works)bool(0) → False, bool(1) → True, bool("") → False, bool([]) → False (Truthiness)str(5) + " apples" → "5 apples"Safe Casting Pattern (With Error Handling):
try:
age = int(input("Enter your age: "))
print(f"Next year you'll be {age + 1}")
except ValueError:
print("Please enter a valid number.")
1.5 Combining Expressions and Built-in Functions
Complex Expression Examples (Read and Analyze):
# Example 1: Calculate average with error handling
scores = [85, 92, 78, 90, 88]
average = sum(scores) / len(scores)
print(f"Average: {round(average, 2)}")
# Example 2: Validate and process input
user_input = input("Enter a number: ")
squared = pow(float(user_input), 2)
print(f"Square: {squared}")
# Example 3: String manipulation with length check
text = " Hello, World! "
cleaned = text.strip()
print(f"Length: {len(cleaned)}")
print(f"Uppercase: {cleaned.upper()}")
# Example 4: Complex conditional expression
age = 22
height = 1.8
is_eligible = age >= 18 and height > 1.5 and (age < 60 or height > 1.9)
print(is_eligible) # True
# --- Understanding Expressions ---
print("--- Expressions Demystified ---")
# Literal expressions
print(42) # 42
print("Hello") # Hello
# Arithmetic expressions
result = 10 + 5 * 2 # 20 (multiplication before addition)
print(result)
# Function call expressions
print(len("Python")) # 6
# Combined expressions
total = sum([1, 2, 3]) + len("ABC") * 2 # 6 + 6 = 12
print(total)
# --- Operator Precedence (Step-by-Step Evaluation) ---
print("\n--- Operator Precedence ---")
# Expression: 10 + 3 * 2 ** 2
# Step 1: 2 ** 2 = 4 (exponentiation first)
# Step 2: 3 * 4 = 12 (multiplication)
# Step 3: 10 + 12 = 22
result = 10 + 3 * 2 ** 2
print(result) # 22
# With explicit parentheses for clarity
result_clear = 10 + (3 * (2 ** 2))
print(result_clear) # 22
# Right-associativity of exponentiation
print(2 ** 3 ** 2) # 512 (2 ** 9)
print((2 ** 3) ** 2) # 64 (8 ** 2)
# --- Built-in Functions in Action ---
print("\n--- Built-in Functions ---")
# len() - works on sequences
name = "Alice"
fruits = ["apple", "banana", "cherry"]
person = {"name": "Bob", "age": 30}
print(f"len(name): {len(name)}") # 5
print(f"len(fruits): {len(fruits)}") # 3
print(f"len(person): {len(person)}") # 2 (keys count)
# type() - inspect data types
print(f"type(42): {type(42)}")
print(f"type(3.14): {type(3.14)}")
print(f"type('Hello'): {type('Hello')}")
# Type casting (int, float, str)
num_str = "25.5"
num_float = float(num_str)
num_int = int(num_float) # Truncates! 25.5 -> 25
print(f"float('25.5'): {num_float}")
print(f"int(25.5): {num_int}")
print(f"str(100): {str(100)}")
# abs(), round(), max(), min()
print(f"abs(-15): {abs(-15)}") # 15
print(f"round(3.14159, 2): {round(3.14159, 2)}") # 3.14
print(f"round(2.5): {round(2.5)}") # 2 (banker's rounding)
print(f"max([10, 20, 15]): {max([10, 20, 15])}") # 20
print(f"min([10, 20, 15]): {min([10, 20, 15])}") # 10
# String methods with len()
text = " Python "
print(f"len(text): {len(text)}") # 9
cleaned = text.strip()
print(f"len(cleaned): {len(cleaned)}") # 6
print(f"cleaned.upper(): {cleaned.upper()}") # PYTHON
# --- Complex Expression Example ---
print("\n--- Complex Expression ---")
scores = [70, 85, 92, 68, 79]
average = sum(scores) / len(scores)
rounded_avg = round(average, 1)
max_score = max(scores)
min_score = min(scores)
print(f"Scores: {scores}")
print(f"Average: {rounded_avg}")
print(f"Range: {min_score} to {max_score}")
print(f"Max is above 90? {max_score > 90}")
Question 1: Which of the following is an expression (as opposed to a statement)?
a) x = 10 + 5
b) 10 + 5
c) if x > 0:
d) print("Hello")
Question 2: What is the value of 3 + 4 * 5 - 2?
a) 33
b) 21
c) -15
d) 25
Question 3: What is the value of 2 ** 3 ** 2?
a) 64
b) 512
c) 12
d) 81
Question 4: What does len("Hello, World!") return?
a) 12
b) 13
c) 11
d) 14
Question 5: What is the output of int(3.99)?
a) 4
b) 3.99
c) 3
d) ValueError
Question 6: What does type(True) return?
a) <class 'bool'>
b) <class 'int'>
c) True
d) <class 'str'>
Question 7: What is the result of round(2.675, 2)?
a) 2.68
b) 2.67
c) 2.7
d) 2.675
Question 8: What does max([5, 10, 3]) + min([5, 10, 3]) evaluate to?
a) 15
b) 13
c) 5
d) 10
Question 9: Which expression correctly calculates the average of a list scores = [8, 9, 7, 10]?
a) scores / len(scores)
b) sum(scores) / len(scores)
c) sum(scores) // len(scores)
d) len(scores) / sum(scores)
Question 10: What is the output of len(" Python ".strip())?
a) 9
b) 6
c) 7
d) 5
Exercise 1: Expression Calculator Write a Python script that calculates and prints the result of the following expressions. First, predict the result manually, then verify with Python.
(5 + 3) * 2 - 410 / 3 + 2 * 4(2 ** 3) + 4 * 5 // 2len("Python") * 2 + len("is fun")max(10, 20, 15) * min(5, 3, 8)Exercise 2: Type Conversion Tool Write a program that:
Enter a number: 4.7
Float: 4.7 (type: <class 'float'>)
Integer: 4 (type: <class 'int'>)
String: 4 (type: <class 'str'>)
Exercise 3: String Analyzer Write a program that:
.strip()..count('e')).Exercise 4: Grade Calculator
You have a list of grades: grades = [78, 92, 85, 88, 91, 67, 84].
Write a program that calculates and prints:
True or False)."""
GRADE CALCULATOR
Using built-in functions to analyze a list of grades
"""
# Given list of grades
grades = [78, 92, 85, 88, 91, 67, 84]
print("=" * 50)
print("GRADE CALCULATOR")
print("=" * 50)
# Display the grades
print(f"\nGrades: {grades}")
print(f"Number of grades: {len(grades)}")
print("\n" + "-" * 50)
print("RESULTS")
print("-" * 50)
# 1. Calculate total sum using sum()
total = sum(grades)
print(f"1. Total sum of all grades: {total}")
# 2. Calculate average using sum() / len()
# Round to 2 decimal places using round()
average = total / len(grades)
average_rounded = round(average, 2)
print(f"2. Average grade: {average_rounded}")
# 3. Find the highest grade using max()
highest = max(grades)
print(f"3. Highest grade: {highest}")
# 4. Find the lowest grade using min()
lowest = min(grades)
print(f"4. Lowest grade: {lowest}")
# 5. Check if average is greater than 80 (produces True/False)
is_above_80 = average > 80
print(f"5. Average is greater than 80: {is_above_80}")
print("\n" + "-" * 50)
print("ADDITIONAL ANALYSIS")
print("-" * 50)
# Bonus: Count how many grades are above average
above_average = [grade for grade in grades if grade > average]
count_above = len(above_average)
print(f"Grades above average ({average_rounded}): {count_above}")
# Bonus: Grades sorted in ascending order
sorted_grades = sorted(grades)
print(f"Grades sorted: {sorted_grades}")
# Bonus: Range (highest - lowest)
range_grades = highest - lowest
print(f"Range of grades: {range_grades}")
# Bonus: Letter grade breakdown
def get_letter_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
print("\nLetter grade breakdown:")
for grade in sorted_grades:
letter = get_letter_grade(grade)
print(f" {grade} → {letter}")
print("\n" + "=" * 50)
print("KEY FUNCTIONS USED:")
print("=" * 50)
print(" • sum(list) - Sums all elements")
print(" • len(list) - Returns the length (number of items)")
print(" • max(list) - Returns the maximum value")
print(" • min(list) - Returns the minimum value")
print(" • round(value, decimals) - Rounds to specified decimals")
print(" • sorted(list) - Returns a sorted copy of the list")
print("=" * 50)
Sample Output:
==================================================
GRADE CALCULATOR
==================================================
Grades: [78, 92, 85, 88, 91, 67, 84]
Number of grades: 7
--------------------------------------------------
RESULTS
--------------------------------------------------
1. Total sum of all grades: 585
2. Average grade: 83.57
3. Highest grade: 92
4. Lowest grade: 67
5. Average is greater than 80: True
--------------------------------------------------
ADDITIONAL ANALYSIS
--------------------------------------------------
Grades above average (83.57): 4
Grades sorted: [67, 78, 84, 85, 88, 91, 92]
Range of grades: 25
Letter grade breakdown:
67 → D
78 → C
84 → B
85 → B
88 → B
91 → A
92 → A
==================================================
KEY FUNCTIONS USED:
==================================================
• sum(list) - Sums all elements
• len(list) - Returns the length (number of items)
• max(list) - Returns the maximum value
• min(list) - Returns the minimum value
• round(value, decimals) - Rounds to specified decimals
• sorted(list) - Returns a sorted copy of the list
==================================================
Explanation of Key Concepts:
sum(grades) – Adds all elements in the list efficiently.len(grades) – Returns the count of elements for calculating the average.max(grades) / min(grades) – Find the highest and lowest values.round(average, 2) – Formats the average to 2 decimal places for readability.average > 80 – A comparison expression that automatically returns True or False.Alternative Approach (Manual Loop):
If you want to understand the logic without built-in functions:
grades = [78, 92, 85, 88, 91, 67, 84]
# Manual sum using a loop
total = 0
for grade in grades:
total += grade
# Manual max/min using a loop
highest = grades[0]
lowest = grades[0]
for grade in grades:
if grade > highest:
highest = grade
if grade < lowest:
lowest = grade
# Calculate average
average = total / len(grades)
print(f"Sum: {total}")
print(f"Average: {round(average, 2)}")
print(f"Highest: {highest}")
print(f"Lowest: {lowest}")
print(f"Average > 80: {average > 80}")
Exercise 5: Expression Rewrite
Rewrite the following expressions to make the order of operations explicit using parentheses, and then evaluate them:
a = 5 + 3 * 2b = 10 - 2 ** 3 + 4c = 15 / 3 * 2 + 1d = len("hello") * 2 + 5"""
EXPRESSION REWRITE
Making operator precedence explicit using parentheses
"""
print("=" * 60)
print("EXPRESSION REWRITE - ORDER OF OPERATIONS")
print("=" * 60)
print("\n" + "-" * 60)
print("Original Expression 1: a = 5 + 3 * 2")
print("-" * 60)
# Step-by-step evaluation
print("\nOriginal evaluation (without parentheses):")
print(" 5 + 3 * 2 = 5 + 6 = 11")
print(f" a = {5 + 3 * 2}")
# Rewritten with explicit parentheses (multiplication first)
print("\nRewritten with explicit parentheses:")
print(" a = 5 + (3 * 2)")
print(" a = 5 + 6 = 11")
print(f" a = {5 + (3 * 2)}")
print("\n" + "-" * 60)
print("Original Expression 2: b = 10 - 2 ** 3 + 4")
print("-" * 60)
# Step-by-step evaluation
print("\nOriginal evaluation (without parentheses):")
print(" Step 1: 2 ** 3 = 8")
print(" Step 2: 10 - 8 + 4 = 2 + 4 = 6")
print(f" b = {10 - 2 ** 3 + 4}")
# Rewritten with explicit parentheses (exponentiation first)
print("\nRewritten with explicit parentheses:")
print(" b = 10 - (2 ** 3) + 4")
print(" b = 10 - 8 + 4 = 2 + 4 = 6")
print(f" b = {10 - (2 ** 3) + 4}")
# Alternative interpretation (if you wanted subtraction first)
print("\nAlternative (if you wanted subtraction first):")
print(" b = (10 - 2) ** 3 + 4")
print(" b = 8 ** 3 + 4 = 512 + 4 = 516")
print(f" b = {(10 - 2) ** 3 + 4}")
print("\n" + "-" * 60)
print("Original Expression 3: c = 15 / 3 * 2 + 1")
print("-" * 60)
# Step-by-step evaluation
print("\nOriginal evaluation (without parentheses):")
print(" Step 1: 15 / 3 = 5.0")
print(" Step 2: 5.0 * 2 = 10.0")
print(" Step 3: 10.0 + 1 = 11.0")
print(f" c = {15 / 3 * 2 + 1}")
# Rewritten with explicit parentheses
print("\nRewritten with explicit parentheses:")
print(" c = ((15 / 3) * 2) + 1")
print(" c = (5.0 * 2) + 1 = 10.0 + 1 = 11.0")
print(f" c = {((15 / 3) * 2) + 1}")
# Alternative interpretation (if you wanted division last)
print("\nAlternative (if you wanted multiplication first):")
print(" c = 15 / (3 * 2) + 1")
print(" c = 15 / 6 + 1 = 2.5 + 1 = 3.5")
print(f" c = {15 / (3 * 2) + 1}")
print("\n" + "-" * 60)
print("Original Expression 4: d = len(\"hello\") * 2 + 5")
print("-" * 60)
# Step-by-step evaluation
print("\nOriginal evaluation (without parentheses):")
print(" Step 1: len(\"hello\") = 5")
print(" Step 2: 5 * 2 + 5 = 10 + 5 = 15")
print(f" d = {len('hello') * 2 + 5}")
# Rewritten with explicit parentheses
print("\nRewritten with explicit parentheses:")
print(" d = (len(\"hello\") * 2) + 5")
print(" d = (5 * 2) + 5 = 10 + 5 = 15")
print(f" d = {(len('hello') * 2) + 5}")
# Alternative interpretation (if you wanted addition first)
print("\nAlternative (if you wanted addition first):")
print(" d = len(\"hello\") * (2 + 5)")
print(" d = 5 * 7 = 35")
print(f" d = {len('hello') * (2 + 5)}")
print("\n" + "-" * 60)
print("SUMMARY TABLE")
print("-" * 60)
print("\n| Expression | Original Result | Rewritten Expression | Rewritten Result |")
print("|------------|-----------------|----------------------|------------------|")
results = [
("a = 5 + 3 * 2", 11, "a = 5 + (3 * 2)", 11),
("b = 10 - 2 ** 3 + 4", 6, "b = 10 - (2 ** 3) + 4", 6),
("c = 15 / 3 * 2 + 1", 11.0, "c = ((15 / 3) * 2) + 1", 11.0),
("d = len('hello') * 2 + 5", 15, "d = (len('hello') * 2) + 5", 15),
]
for orig_expr, orig_result, rewritten, rewritten_result in results:
print(f"| {orig_expr:<10} | {orig_result:>15} | {rewritten:<20} | {rewritten_result:>17} |")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS:")
print("=" * 60)
print(" • Parentheses make the order of operations EXPLICIT")
print(" • Different parentheses placement can change the result")
print(" • In real code, use parentheses for clarity and to avoid bugs")
print(" • Operator precedence: () > ** > *,/,//,% > +,-")
print(" • 'len()' is a function call (evaluated before arithmetic)")
print("=" * 60)
Sample Output:
============================================================
EXPRESSION REWRITE - ORDER OF OPERATIONS
============================================================
------------------------------------------------------------
Original Expression 1: a = 5 + 3 * 2
------------------------------------------------------------
Original evaluation (without parentheses):
5 + 3 * 2 = 5 + 6 = 11
a = 11
Rewritten with explicit parentheses:
a = 5 + (3 * 2)
a = 5 + 6 = 11
a = 11
------------------------------------------------------------
Original Expression 2: b = 10 - 2 ** 3 + 4
------------------------------------------------------------
Original evaluation (without parentheses):
Step 1: 2 ** 3 = 8
Step 2: 10 - 8 + 4 = 2 + 4 = 6
b = 6
Rewritten with explicit parentheses:
b = 10 - (2 ** 3) + 4
b = 10 - 8 + 4 = 2 + 4 = 6
b = 6
Alternative (if you wanted subtraction first):
b = (10 - 2) ** 3 + 4
b = 8 ** 3 + 4 = 512 + 4 = 516
b = 516
------------------------------------------------------------
Original Expression 3: c = 15 / 3 * 2 + 1
------------------------------------------------------------
Original evaluation (without parentheses):
Step 1: 15 / 3 = 5.0
Step 2: 5.0 * 2 = 10.0
Step 3: 10.0 + 1 = 11.0
c = 11.0
Rewritten with explicit parentheses:
c = ((15 / 3) * 2) + 1
c = (5.0 * 2) + 1 = 10.0 + 1 = 11.0
c = 11.0
Alternative (if you wanted multiplication first):
c = 15 / (3 * 2) + 1
c = 15 / 6 + 1 = 2.5 + 1 = 3.5
c = 3.5
------------------------------------------------------------
Original Expression 4: d = len("hello") * 2 + 5
------------------------------------------------------------
Original evaluation (without parentheses):
Step 1: len("hello") = 5
Step 2: 5 * 2 + 5 = 10 + 5 = 15
d = 15
Rewritten with explicit parentheses:
d = (len("hello") * 2) + 5
d = (5 * 2) + 5 = 10 + 5 = 15
d = 15
Alternative (if you wanted addition first):
d = len("hello") * (2 + 5)
d = 5 * 7 = 35
d = 35
------------------------------------------------------------
SUMMARY TABLE
------------------------------------------------------------
| Expression | Original Result | Rewritten Expression | Rewritten Result |
|------------|-----------------|----------------------|------------------|
| a = 5 + 3 * 2 | 11 | a = 5 + (3 * 2) | 11 |
| b = 10 - 2 ** 3 + 4 | 6 | b = 10 - (2 ** 3) + 4 | 6 |
| c = 15 / 3 * 2 + 1 | 11.0 | c = ((15 / 3) * 2) + 1 | 11.0 |
| d = len('hello') * 2 + 5 | 15 | d = (len('hello') * 2) + 5 | 15 |
============================================================
KEY TAKEAWAYS:
============================================================
• Parentheses make the order of operations EXPLICIT
• Different parentheses placement can change the result
• In real code, use parentheses for clarity and to avoid bugs
• Operator precedence: () > ** > *,/,//,% > +,-
• 'len()' is a function call (evaluated before arithmetic)
============================================================
Explanation of Each Expression:
1. a = 5 + 3 * 2
*) before addition (+).3 * 2 = 65 + 6 = 11a = 5 + (3 * 2)2. b = 10 - 2 ** 3 + 4
**) first, then addition/subtraction left-to-right.2 ** 3 = 810 - 8 = 22 + 4 = 6b = 10 - (2 ** 3) + 4(10 - 2) ** 3 + 4, the result would be 516 (demonstrating the importance of parentheses).3. c = 15 / 3 * 2 + 1
/) and multiplication (*) are left-to-right, then addition (+).15 / 3 = 5.05.0 * 2 = 10.010.0 + 1 = 11.0c = ((15 / 3) * 2) + 115 / (3 * 2) + 1, the result would be 3.5 (showing how parentheses change the result).4. d = len("hello") * 2 + 5
len()) is evaluated first (like parentheses), then multiplication, then addition.len("hello") = 55 * 2 = 1010 + 5 = 15d = (len("hello") * 2) + 5len("hello") * (2 + 5), the result would be 35.Key Takeaways:
() > ** > *, /, //, % > +, -** is right-to-left.len() are evaluated like parentheses.Complete Code with Interactive Testing:
# Interactive version - test your understanding
print("Test your understanding by predicting the results:")
print("=" * 50)
test_expressions = [
("10 + 2 * 5", "10 + (2 * 5)"),
("8 / 2 * 4", "(8 / 2) * 4"),
("3 ** 2 + 1", "(3 ** 2) + 1"),
("5 + 3 * 2 ** 2", "5 + (3 * (2 ** 2))"),
]
for expr, rewritten in test_expressions:
original_result = eval(expr)
rewritten_result = eval(rewritten)
print(f"Original: {expr} = {original_result}")
print(f"Rewritten: {rewritten} = {rewritten_result}")
print(f"Same result: {original_result == rewritten_result}")
print("-" * 50)
Question 1 (Precedence Puzzle):
Without running the code, determine the value of x after this expression. Show your step-by-step evaluation:
x = 10 + 4 * 2 ** 3 // 2 - 1
Hint: Remember exponentiation first, then multiplication/division/floordivision left-to-right, then addition/subtraction.
Question 2 (Built-in Function Investigative):
Research the following built-in functions online or in the Python documentation: pow(), divmod(), ord(), chr(). Write a short explanation of what each does and provide an example of using each in a Python expression.
Question 3 (Real-World Application – Investment Calculator):
Write a complete Python program that:
Asks the user for:
Calculates the future value using the formula:
future_value = principal * (1 + rate/100) ** years
Prints the result with exactly 2 decimal places.
Bonus: Print the total interest earned (future_value - principal) rounded to 2 decimal places.
Challenge: Use the pow() function instead of the ** operator.
"""
INVESTMENT CALCULATOR
Calculates future value of an investment using compound interest
"""
print("=" * 60)
print("INVESTMENT CALCULATOR")
print("=" * 60)
# --- Step 1: Get user input with error handling ---
print("\nEnter your investment details:")
try:
# Get principal (initial investment)
principal = float(input(" Initial investment amount: $"))
if principal < 0:
print(" Warning: Investment amount should be positive.")
principal = abs(principal)
# Get annual interest rate (as a percentage)
rate = float(input(" Annual interest rate (as %): "))
if rate < 0:
print(" Warning: Interest rate should be positive.")
rate = abs(rate)
# Get number of years
years = int(input(" Number of years: "))
if years < 0:
print(" Warning: Years should be positive.")
years = abs(years)
except ValueError:
print("\nInvalid input! Please enter valid numbers.")
print("Using default values: $1000, 5%, 10 years")
principal = 1000.0
rate = 5.0
years = 10
print("\n" + "-" * 60)
print("INVESTMENT DETAILS")
print("-" * 60)
print(f"Principal: ${principal:,.2f}")
print(f"Interest Rate: {rate}%")
print(f"Years: {years}")
# --- Step 2: Calculate future value ---
# Method 1: Using the ** operator (as specified in the formula)
future_value_operator = principal * (1 + rate / 100) ** years
interest_earned_operator = future_value_operator - principal
# Method 2: Using the pow() function (challenge)
future_value_pow = principal * pow((1 + rate / 100), years)
interest_earned_pow = future_value_pow - principal
print("\n" + "-" * 60)
print("CALCULATION")
print("-" * 60)
# --- Step 3 & Bonus: Print results with proper formatting ---
print("\nUsing ** operator:")
print(f" Future Value: ${future_value_operator:,.2f}")
# Bonus: Print total interest earned
print(f" Interest Earned: ${interest_earned_operator:,.2f}")
print("\nUsing pow() function (Challenge):")
print(f" Future Value: ${future_value_pow:,.2f}")
print(f" Interest Earned: ${interest_earned_pow:,.2f}")
# Verify both methods produce the same result
if future_value_operator == future_value_pow:
print("\n✅ Both methods produce the same result!")
print("\n" + "-" * 60)
print("ADDITIONAL ANALYSIS")
print("-" * 60)
# --- Additional useful information ---
# Calculate the total percentage growth
growth_percentage = ((future_value_operator - principal) / principal) * 100
print(f"Total Growth: {growth_percentage:.1f}%")
# Calculate the annualized return
annualized_return = (future_value_operator / principal) ** (1 / years) - 1
print(f"Annualized Return: {annualized_return:.2%}")
# Show year-by-year growth
print("\nYear-by-year growth:")
print(" Year | Balance")
print(" -----|-----------")
current_balance = principal
for year in range(1, years + 1):
current_balance = current_balance * (1 + rate / 100)
print(f" {year:>4} | ${current_balance:>9,.2f}")
print("\n" + "-" * 60)
print("ADDITIONAL SCENARIOS")
print("-" * 60)
# --- Compare with different rates ---
rates_to_test = [3, 5, 7, 10]
print("\nFuture value with different interest rates:")
print(" Rate | Future Value | Interest Earned")
print(" -----|--------------|-----------------")
for test_rate in rates_to_test:
test_future = principal * (1 + test_rate / 100) ** years
test_interest = test_future - principal
print(f" {test_rate:>4}% | ${test_future:>11,.2f} | ${test_interest:>14,.2f}")
# --- Rule of 72 check ---
approx_doubling_time = 72 / rate
print(f"\nRule of 72 estimate: Investment doubles in approximately {approx_doubling_time:.1f} years")
if years >= approx_doubling_time:
print(f"✅ Your investment of {years} years is long enough to approximately double!")
else:
print(f"⚠️ Your investment of {years} years is shorter than the estimated doubling time.")
print("\n" + "=" * 60)
print("KEY FORMULAS USED:")
print("=" * 60)
print(" • Future Value = P × (1 + r/100)^n")
print(" • Interest Earned = Future Value - Principal")
print(" • pow(base, exponent) is equivalent to base ** exponent")
print(" • Annualized Return = (FV/P)^(1/n) - 1")
print("=" * 60)
# --- Challenge: Using pow() with built-in functions ---
print("\n" + "=" * 60)
print("COMPARISON OF METHODS")
print("=" * 60)
def calculate_future_value(principal, rate, years, method='operator'):
"""
Calculate future value using different methods.
"""
if method == 'operator':
return principal * (1 + rate / 100) ** years
elif method == 'pow':
return principal * pow(1 + rate / 100, years)
elif method == 'manual':
# Manual calculation using a loop
result = principal
for _ in range(years):
result *= (1 + rate / 100)
return result
else:
raise ValueError("Invalid method")
# Test all three methods
methods = ['operator', 'pow', 'manual']
method_names = ['** operator', 'pow() function', 'Manual loop']
print("\nTesting all three calculation methods:")
print("-" * 60)
for method, name in zip(methods, method_names):
result = calculate_future_value(principal, rate, years, method)
print(f" {name:15} → ${result:,.2f}")
print("\n" + "=" * 60)
Sample Output:
============================================================
INVESTMENT CALCULATOR
============================================================
Enter your investment details:
Initial investment amount: $1000
Annual interest rate (as %): 5
Number of years: 10
------------------------------------------------------------
INVESTMENT DETAILS
------------------------------------------------------------
Principal: $1,000.00
Interest Rate: 5.0%
Years: 10
------------------------------------------------------------
CALCULATION
------------------------------------------------------------
Using ** operator:
Future Value: $1,628.89
Interest Earned: $628.89
Using pow() function (Challenge):
Future Value: $1,628.89
Interest Earned: $628.89
✅ Both methods produce the same result!
------------------------------------------------------------
ADDITIONAL ANALYSIS
------------------------------------------------------------
Total Growth: 62.9%
Annualized Return: 5.00%
Year-by-year growth:
Year | Balance
-----|-----------
1 | $1,050.00
2 | $1,102.50
3 | $1,157.63
4 | $1,215.51
5 | $1,276.28
6 | $1,340.10
7 | $1,407.10
8 | $1,477.46
9 | $1,551.33
10 | $1,628.89
------------------------------------------------------------
ADDITIONAL SCENARIOS
------------------------------------------------------------
Future value with different interest rates:
Rate | Future Value | Interest Earned
-----|--------------|-----------------
3% | $1,343.92 | $343.92
5% | $1,628.89 | $628.89
7% | $1,967.15 | $967.15
10% | $2,593.74 | $1,593.74
Rule of 72 estimate: Investment doubles in approximately 14.4 years
⚠️ Your investment of 10 years is shorter than the estimated doubling time.
============================================================
KEY FORMULAS USED:
============================================================
• Future Value = P × (1 + r/100)^n
• Interest Earned = Future Value - Principal
• pow(base, exponent) is equivalent to base ** exponent
• Annualized Return = (FV/P)^(1/n) - 1
============================================================
============================================================
COMPARISON OF METHODS
============================================================
Testing all three calculation methods:
------------------------------------------------------------
** operator → $1,628.89
pow() function → $1,628.89
Manual loop → $1,628.89
============================================================
Explanation:
Key Concepts:
Compound Interest Formula:
Future Value = Principal × (1 + Rate/100)^Years
Rate/100 converts percentage to decimal (e.g., 5% → 0.05)^Years compounds the interest over multiple yearsUsing ** vs pow():
x ** y is the exponentiation operatorpow(x, y) is the built-in function that does the same thingpow() can optionally take a third argument for modulusFormatting:
{value:,.2f} adds thousands separators and 2 decimal places{rate:.1%} formats as percentage with 1 decimal placeError Handling:
try/except catches invalid inputsManual Loop Method:
Alternative Approach (Simpler Version):
# Simpler version without all the extras
principal = float(input("Enter initial investment: $"))
rate = float(input("Enter annual interest rate (%): "))
years = int(input("Enter number of years: "))
# Method 1: Using ** operator
future_value = principal * (1 + rate/100) ** years
print(f"Future Value: ${future_value:,.2f}")
# Bonus: Interest earned
interest_earned = future_value - principal
print(f"Interest Earned: ${interest_earned:,.2f}")
# Challenge: Using pow()
future_value_pow = principal * pow(1 + rate/100, years)
print(f"Using pow(): ${future_value_pow:,.2f}")
Question 4 (Exploration – sum() with Strings):
What happens if you try to use sum() on a list of strings: sum(["a", "b", "c"])? Try it in your head or research why. What is the error message? Why does this happen? How would you concatenate a list of strings instead (hint: "".join())?
What Happens:
When you try to use sum() on a list of strings:
sum(["a", "b", "c"])
You get a TypeError with the message:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Why This Happens:
sum() is designed for numeric addition:
sum() function starts with an initial value of 0 (an integer)0 + "a" is an invalid operation because you cannot add an integer and a stringThe + operator for strings has a different meaning:
+ means concatenation (joining strings together)+ means arithmetic additionsum() expects arithmetic addition, not string concatenationInternal implementation: The sum() function is implemented something like:
def sum(iterable, start=0):
total = start
for item in iterable:
total = total + item # This fails when total is int and item is str
return total
Demonstration:
# The problem in action
try:
result = sum(["a", "b", "c"])
except TypeError as e:
print(f"Error: {e}")
# This fails because: 0 + "a" is invalid
How to Concatenate a List of Strings:
The correct way to join strings is using the join() method:
# Method 1: Using join() - RECOMMENDED
strings = ["a", "b", "c"]
result = "".join(strings)
print(result) # Output: "abc"
# Method 2: Using join with a separator
result = ", ".join(strings)
print(result) # Output: "a, b, c"
# Method 3: Using a loop (inefficient, but works)
result = ""
for s in strings:
result += s
print(result) # Output: "abc"
# Method 4: Using reduce() from functools (alternative)
from functools import reduce
result = reduce(lambda x, y: x + y, strings)
print(result) # Output: "abc"
Why join() is Better:
join() is implemented in C and is much faster than loopingjoin() allocates memory once, while += creates multiple intermediate strings"".join(list) clearly shows the intent to concatenateComplete Example:
print("=" * 60)
print("SUMMING STRINGS - EXPLORATION")
print("=" * 60)
strings = ["a", "b", "c"]
print(f"List of strings: {strings}")
print("\n" + "-" * 60)
print("ATTEMPTING sum() ON STRINGS")
print("-" * 60)
try:
result = sum(strings)
print(f"sum(strings) = {result}")
except TypeError as e:
print(f"Error: {e}")
print("\nExplanation:")
print(" • sum() starts with initial value 0 (integer)")
print(" • Then tries: 0 + 'a', which is invalid")
print(" • '+' means arithmetic addition for numbers")
print(" • '+' means string concatenation for strings")
print(" • These operations are incompatible")
print("\n" + "-" * 60)
print("CORRECT WAYS TO CONCATENATE STRINGS")
print("-" * 60)
# Method 1: join() - RECOMMENDED
result_join = "".join(strings)
print(f'Method 1 - "".join(strings): "{result_join}"')
# Method 2: join() with separator
result_join_sep = ", ".join(strings)
print(f'Method 2 - ", ".join(strings): "{result_join_sep}"')
# Method 3: Loop with +=
result_loop = ""
for s in strings:
result_loop += s
print(f'Method 3 - Loop with +=: "{result_loop}"')
# Method 4: reduce from functools
from functools import reduce
result_reduce = reduce(lambda x, y: x + y, strings)
print(f'Method 4 - reduce: "{result_reduce}"')
# Method 5: Multiple parameters in print()
print('Method 5 - print(*strings):', *strings, sep="")
print("\n" + "-" * 60)
print("PERFORMANCE COMPARISON")
print("-" * 60)
import time
# Test with a larger list
large_list = ["a"] * 10000
print("Testing performance with 10,000 strings:")
# Method 1: join() - Fast
start = time.time()
result_join = "".join(large_list)
time_join = time.time() - start
print(f' join(): {time_join:.6f} seconds')
# Method 2: Loop with += - Slow
start = time.time()
result_loop = ""
for s in large_list:
result_loop += s
time_loop = time.time() - start
print(f' Loop with +=: {time_loop:.6f} seconds')
print(f' join() is {time_loop/time_join:.1f}x faster!')
print("\n" + "=" * 60)
print("SUMMARY")
print("=" * 60)
print(" • sum() requires numeric operands (int, float)")
print(" • sum() cannot be used for string concatenation")
print(" • Use ''.join(list) for concatenating strings")
print(" • join() is more efficient than looping with +=")
print("=" * 60)
Sample Output:
============================================================
SUMMING STRINGS - EXPLORATION
============================================================
List of strings: ['a', 'b', 'c']
------------------------------------------------------------
ATTEMPTING sum() ON STRINGS
------------------------------------------------------------
Error: unsupported operand type(s) for +: 'int' and 'str'
Explanation:
• sum() starts with initial value 0 (integer)
• Then tries: 0 + 'a', which is invalid
• '+' means arithmetic addition for numbers
• '+' means string concatenation for strings
• These operations are incompatible
------------------------------------------------------------
CORRECT WAYS TO CONCATENATE STRINGS
------------------------------------------------------------
Method 1 - "".join(strings): "abc"
Method 2 - ", ".join(strings): "a, b, c"
Method 3 - Loop with +=: "abc"
Method 4 - reduce: "abc"
Method 5 - print(*strings): abc
------------------------------------------------------------
PERFORMANCE COMPARISON
------------------------------------------------------------
Testing performance with 10,000 strings:
join(): 0.000123 seconds
Loop with +=: 0.001234 seconds
join() is 10.0x faster!
============================================================
SUMMARY
============================================================
• sum() requires numeric operands (int, float)
• sum() cannot be used for string concatenation
• Use ''.join(list) for concatenating strings
• join() is more efficient than looping with +=
============================================================
Key Takeaways:
sum() is for numeric addition only – It cannot concatenate strings.
Type Compatibility: sum() expects all elements to be numbers (int or float).
Why the Error Occurs: sum() starts with 0, and 0 + "a" is invalid.
Correct Tool: Use "".join(list_of_strings) to concatenate strings.
Performance: join() is much more efficient than using += in a loop.
Flexibility: join() allows you to specify any separator string.
Memory Efficiency: join() allocates memory once, while += creates multiple intermediate strings.
Question 5 (Mini-Project: Data Validator):
Write a program that does the following:
student = {"name": "Alex", "grades": [85, 92, 78, 90]}.round())."""
DATA VALIDATOR - STUDENT GRADES
Demonstrates working with dictionaries, lists, and built-in functions
"""
print("=" * 60)
print("STUDENT DATA VALIDATOR")
print("=" * 60)
# --- Step 1: Create the student dictionary ---
student = {
"name": "Alex",
"grades": [85, 92, 78, 90]
}
print("\nInitial Student Data:")
print(f" Name: {student['name']}")
print(f" Grades: {student['grades']}")
# --- Step 2: Analyze the data using built-in functions ---
print("\n" + "-" * 60)
print("INITIAL ANALYSIS")
print("-" * 60)
# 2.1: Print name in uppercase
uppercase_name = student['name'].upper()
print(f"Name (uppercase): {uppercase_name}")
# 2.2: Calculate and print average (rounded to 1 decimal)
grades = student['grades']
total = sum(grades)
count = len(grades)
average = total / count
average_rounded = round(average, 1)
print(f"Average grade: {average_rounded}")
# 2.3: Print highest and lowest grade
highest = max(grades)
lowest = min(grades)
print(f"Highest grade: {highest}")
print(f"Lowest grade: {lowest}")
# 2.4: Pass/Fail check
is_passing = average >= 80
print(f"Average >= 80: {is_passing}")
if is_passing:
print("Status: ✅ PASS")
else:
print("Status: ❌ FAIL")
# --- Additional analysis (Bonus) ---
print("\n" + "-" * 60)
print("ADDITIONAL STATISTICS")
print("-" * 60)
# Grade range
grade_range = highest - lowest
print(f"Grade range: {grade_range}")
# Count grades above and below average
above_average = [g for g in grades if g > average]
below_average = [g for g in grades if g < average]
print(f"Grades above average: {len(above_average)}")
print(f"Grades below average: {len(below_average)}")
# Letter grade distribution
def get_letter_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
letter_grades = [get_letter_grade(g) for g in grades]
print(f"Letter grades: {letter_grades}")
# Count each letter grade
for letter in ['A', 'B', 'C', 'D', 'F']:
count_letter = letter_grades.count(letter)
if count_letter > 0:
print(f" {letter}: {count_letter} grade(s)")
# --- Step 3: Ask user for a new grade and recalculate ---
print("\n" + "-" * 60)
print("ADD NEW GRADE")
print("-" * 60)
try:
new_grade_input = input("Enter a new grade to add: ")
new_grade = float(new_grade_input)
# Validate the grade is between 0 and 100
if 0 <= new_grade <= 100:
# Append to the list (mutable operation)
student['grades'].append(new_grade)
print(f"✅ Added grade: {new_grade}")
# Recalculate everything
print("\n" + "-" * 60)
print("UPDATED ANALYSIS")
print("-" * 60)
# Update variables
grades = student['grades']
total = sum(grades)
count = len(grades)
average = total / count
average_rounded = round(average, 1)
highest = max(grades)
lowest = min(grades)
is_passing = average >= 80
# Display updated results
print(f"Grades: {grades}")
print(f"Number of grades: {count}")
print(f"Average grade: {average_rounded}")
print(f"Highest grade: {highest}")
print(f"Lowest grade: {lowest}")
if is_passing:
print("Status: ✅ PASS")
else:
print("Status: ❌ FAIL")
else:
print(f"❌ Invalid grade! Grade must be between 0 and 100. Got: {new_grade}")
except ValueError:
print("❌ Invalid input! Please enter a number.")
# --- Step 4: Final summary ---
print("\n" + "=" * 60)
print("FINAL SUMMARY")
print("=" * 60)
def get_grade_summary(grade):
"""Return a summary of a grade's performance."""
if grade >= 90:
return "Excellent"
elif grade >= 80:
return "Good"
elif grade >= 70:
return "Satisfactory"
elif grade >= 60:
return "Needs Improvement"
else:
return "Failing"
print(f"\nStudent: {student['name']}")
print(f"Number of grades: {len(student['grades'])}")
print(f"Final average: {round(sum(student['grades'])/len(student['grades']), 1)}")
print("\nGrade Summary:")
for i, grade in enumerate(student['grades'], 1):
summary = get_grade_summary(grade)
print(f" Grade {i}: {grade} - {summary}")
print("\n" + "=" * 60)
print("FUNCTIONS USED:")
print("=" * 60)
print(" • sum(list) - Sums all elements")
print(" • len(list) - Gets the length")
print(" • max(list) - Finds the maximum value")
print(" • min(list) - Finds the minimum value")
print(" • round(value, n) - Rounds to n decimal places")
print(" • str.upper() - Converts string to uppercase")
print(" • list.append(item) - Adds an item to the list")
print(" • list.count(item) - Counts occurrences of an item")
print(" • 'in' - Membership test")
print("=" * 60)
Sample Output (Initial Run):
============================================================
STUDENT DATA VALIDATOR
============================================================
Initial Student Data:
Name: Alex
Grades: [85, 92, 78, 90]
------------------------------------------------------------
INITIAL ANALYSIS
------------------------------------------------------------
Name (uppercase): ALEX
Average grade: 86.2
Highest grade: 92
Lowest grade: 78
Average >= 80: True
Status: ✅ PASS
------------------------------------------------------------
ADDITIONAL STATISTICS
------------------------------------------------------------
Grade range: 14
Grades above average: 2
Grades below average: 1
Letter grades: ['B', 'A', 'C', 'A']
A: 2 grade(s)
B: 1 grade(s)
C: 1 grade(s)
------------------------------------------------------------
ADD NEW GRADE
------------------------------------------------------------
Enter a new grade to add: 88
✅ Added grade: 88.0
------------------------------------------------------------
UPDATED ANALYSIS
------------------------------------------------------------
Grades: [85, 92, 78, 90, 88.0]
Number of grades: 5
Average grade: 86.6
Highest grade: 92.0
Lowest grade: 78.0
Status: ✅ PASS
============================================================
FINAL SUMMARY
============================================================
Student: Alex
Number of grades: 5
Final average: 86.6
Grade Summary:
Grade 1: 85 - Good
Grade 2: 92 - Excellent
Grade 3: 78 - Satisfactory
Grade 4: 90 - Excellent
Grade 5: 88.0 - Good
============================================================
FUNCTIONS USED:
============================================================
• sum(list) - Sums all elements
• len(list) - Gets the length
• max(list) - Finds the maximum value
• min(list) - Finds the minimum value
• round(value, n) - Rounds to n decimal places
• str.upper() - Converts string to uppercase
• list.append(item) - Adds an item to the list
• list.count(item) - Counts occurrences of an item
• 'in' - Membership test
============================================================
Alternative Implementation (With Loop for Multiple Grades):
"""
Alternative version - Allows adding multiple grades
"""
print("=" * 60)
print("STUDENT DATA VALIDATOR (Enhanced)")
print("=" * 60)
# Initial student data
student = {
"name": "Alex",
"grades": [85, 92, 78, 90]
}
def analyze_student(student):
"""Analyze and print student grades."""
name = student['name']
grades = student['grades']
print(f"\nStudent: {name}")
print(f"Grades: {grades}")
# Calculations using built-in functions
total = sum(grades)
count = len(grades)
average = total / count
highest = max(grades)
lowest = min(grades)
print(f" Average: {round(average, 1)}")
print(f" Highest: {highest}")
print(f" Lowest: {lowest}")
print(f" Pass/Fail: {'✅ PASS' if average >= 80 else '❌ FAIL'}")
return average
# Initial analysis
print("\nInitial Analysis:")
analyze_student(student)
# Add multiple grades
print("\n" + "-" * 60)
print("Add Multiple Grades")
print("-" * 60)
while True:
try:
grade_input = input("Enter a grade (or 'done' to finish): ")
if grade_input.lower() == 'done':
break
grade = float(grade_input)
if 0 <= grade <= 100:
student['grades'].append(grade)
print(f"✅ Added: {grade}")
else:
print(f"❌ Grade must be between 0 and 100. Got: {grade}")
except ValueError:
print("❌ Invalid input! Enter a number or 'done'.")
# Final analysis
print("\n" + "-" * 60)
print("Final Analysis")
print("-" * 60)
analyze_student(student)
print("\n" + "=" * 60)
print("COMPLETE")
print("=" * 60)
Explanation:
Key Concepts:
Dictionary Access: Use student['name'] and student['grades'] to access data.
List Operations:
sum(grades) – adds all gradeslen(grades) – gets the countmax(grades) – finds the highestmin(grades) – finds the lowestString Methods:
student['name'].upper() – converts to uppercaseList Mutability: student['grades'].append(new_grade) modifies the list in-place.
Formatting:
round(average, 1) – rounds to 1 decimal placeData Flow:
Key Takeaways:
sum(), len(), max(), min() make data analysis easy.round() is essential for formatting numeric output.Write a program that generates random expressions and tests the user's understanding of precedence.
Instructions (Advanced Homework Bonus): Write a program that:
["5 + 3 * 2", "10 / 2 + 3 ** 2", "(5 + 3) * 2 ** 2", "len('hello') + 5 * 2", "max(10, 20, 15) - min(5, 10, 3)"].eval() – Note: Explain that eval() is dangerous in production but safe for this learning exercise).