Previous | Tutorial index | Next
To be able to write augmented assignment statements.
1.1 What are Augmented Assignments?
Augmented assignments are a shorthand notation that combines an arithmetic (or bitwise) operation with an assignment in a single statement. They make code more concise, easier to read, and often more efficient.
The Fundamental Equivalence:
x += 3 is exactly equivalent to x = x + 3
Both statements do the same thing:
x.x.Why Use Augmented Assignments?
counter += 1 are immediately recognizable.1.2 Complete List of Augmented Assignment Operators
| Operator | Shorthand | Equivalent | Description |
|---|---|---|---|
+= |
x += 5 |
x = x + 5 |
Add and assign |
-= |
x -= 5 |
x = x - 5 |
Subtract and assign |
*= |
x *= 5 |
x = x * 5 |
Multiply and assign |
/= |
x /= 5 |
x = x / 5 |
Divide and assign (returns float) |
//= |
x //= 5 |
x = x // 5 |
Floor divide and assign |
%= |
x %= 5 |
x = x % 5 |
Modulo and assign (remainder) |
**= |
x **= 5 |
x = x ** 5 |
Exponentiate and assign |
&= |
x &= 5 |
x = x & 5 |
Bitwise AND and assign |
|= |
x |= 5 |
x = x | 5 |
Bitwise OR and assign |
^= |
x ^= 5 |
x = x ^ 5 |
Bitwise XOR and assign |
<<= |
x <<= 1 |
x = x << 1 |
Left shift and assign |
>>= |
x >>= 1 |
x = x >> 1 |
Right shift and assign |
Note: Bitwise operators are beyond the scope of this unit but are included for completeness.
1.3 How Augmented Assignment Works: Step-by-Step
Example with Numbers (Immutable):
x = 10
print(f"Before: x = {x}, id = {id(x)}")
x += 3
# This is equivalent to: x = x + 3
# Step 1: Read x (10)
# Step 2: Compute 10 + 3 = 13 (creates a new integer object)
# Step 3: Assign 13 back to x (x now points to the new object)
print(f"After: x = {x}, id = {id(x)}") # id will be different!
For immutable types (int, float, str, tuple), augmented assignment always creates a new object and rebinds the variable. This is functionally identical to x = x + value.
For mutable types (list, dict, set), augmented assignment can be different. It often modifies the object in-place rather than creating a new one.
Example with Lists (Mutable):
list1 = [1, 2, 3]
print(f"Before: {list1}, id = {id(list1)}")
list1 += [4, 5] # In-place extension
print(f"After: {list1}, id = {id(list1)}") # SAME id!
# Compare with regular addition (creates a new list):
list2 = [1, 2, 3]
print(f"Before regular: {list2}, id = {id(list2)}")
list2 = list2 + [4, 5] # Creates a new list object
print(f"After regular: {list2}, id = {id(list2)}") # DIFFERENT id!
Why This Difference Matters:
+= on a list) is more memory-efficient because it doesn't create a new list.+= will modify the shared list (affecting both variables). Using list = list + other will create a new list, leaving the original unchanged.1.4 Practical Use Cases: The Accumulator Patterns
Augmented assignments are essential for building cumulative values.
1.4.1 Counter Pattern (Incrementing by 1):
counter = 0
counter += 1 # counter is now 1
counter += 1 # counter is now 2
1.4.2 Summation Accumulator (Running Total):
total = 0
for i in range(1, 6): # i = 1, 2, 3, 4, 5
total += i
print(total) # 15 (1+2+3+4+5)
1.4.3 Product Accumulator (Factorial):
product = 1
for i in range(1, 6): # i = 1, 2, 3, 4, 5
product *= i
print(product) # 120 (5!)
1.4.4 String Building:
message = ""
for word in ["Hello", "World", "Python"]:
message += word + " "
print(message.strip()) # "Hello World Python"
Note: For large strings, using + repeatedly is inefficient. Use " ".join() instead for serious projects.
1.4.5 List Building (Appending via Augmented Assignment):
numbers = []
for i in range(5):
numbers += [i] # Equivalent to numbers.append(i)
print(numbers) # [0, 1, 2, 3, 4]
1.4.6 Cumulative Calculations with *= and **=:
balance = 1000
years = 5
for year in range(years):
balance *= 1.05 # Apply 5% interest each year
print(f"Year {year+1}: ${balance:.2f}")
1.5 Augmented Assignments with Different Data Types
Strings:
greeting = "Hello"
greeting += " World" # greeting = greeting + " World"
print(greeting) # "Hello World"
repeated = "Ha"
repeated *= 3 # repeated = repeated * 3
print(repeated) # "HaHaHa"
Lists:
fruits = ["apple"]
fruits += ["banana", "cherry"] # In-place extension
print(fruits) # ['apple', 'banana', 'cherry']
fruits *= 2 # Doubles the list
print(fruits) # ['apple', 'banana', 'cherry', 'apple', 'banana', 'cherry']
Dictionaries:
# For dictionaries, you can't use += directly (unsupported)
# But you can update with other dictionaries:
inventory = {"apples": 10}
inventory["apples"] += 5 # Update a value (works because we're updating a key)
inventory["bananas"] = 0 # Then later...
inventory["bananas"] += 3 # Works if key exists
print(inventory) # {'apples': 15, 'bananas': 3}
Note: For dictionaries, you typically use dict.update() to merge.
1.6 Common Pitfalls and Mistakes
1.6.1 Uninitialized Variables:
# WRONG: This will raise a NameError
total += 10 # NameError: name 'total' is not defined
# CORRECT: Initialize first
total = 0
total += 10 # Works!
1.6.2 Confusing += with + in Expressions:
# WRONG: Trying to use augmented assignment inside another expression
result = (x += 5) * 2 # SyntaxError
# CORRECT: Do it in two steps
x += 5
result = x * 2
1.6.3 Type Mismatches:
x = 10
x += "5" # TypeError: unsupported operand type(s) for +=: 'int' and 'str'
# Correct way:
x += int("5") # x becomes 15
1.6.4 Integer Division Confusion:
x = 10
x //= 3
print(x) # 3 (integer division)
print(type(x)) # <class 'int'>
y = 10.0
y //= 3
print(y) # 3.0 (float division)
print(type(y)) # <class 'float'>
1.6.5 The List += vs = list + Gotcha:
# Demonstration of aliasing danger
a = [1, 2]
b = a
a += [3] # Modifies the SAME list
print(b) # [1, 2, 3] ← b changed too!
c = [1, 2]
d = c
c = c + [3] # Creates a NEW list
print(d) # [1, 2] ← d is unchanged!
1.7 Performance Considerations
For Immutable Types (int, float, str):
x += y and x = x + y are functionally identical in terms of performance. Both create a new object."".join() instead of += for better performance (O(n²) vs O(n)).For Mutable Types (list, dict, set):
list += other modifies the list in-place, which is more efficient (O(k) where k is length of other).list = list + other creates a new list and is more memory-intensive (O(n+k) where n is length of list).+= for lists when you want to modify the original.Example Showing Performance Difference (Conceptual):
# Less efficient: Creates many intermediate strings
text = ""
for i in range(1000):
text += str(i) # Creates a new string each time
# More efficient: Joins all at once
text = "".join(str(i) for i in range(1000)) # Single string creation
# --- Basic Augmented Assignments ---
print("--- Basic Augmented Assignments ---")
x = 5
print(f"x = {x}")
x += 3 # x = x + 3
print(f"After += 3: {x}")
x -= 2 # x = x - 2
print(f"After -= 2: {x}")
x *= 2 # x = x * 2
print(f"After *= 2: {x}")
x /= 4 # x = x / 4
print(f"After /= 4: {x}")
x //= 2 # x = x // 2
print(f"After //= 2: {x}")
x %= 3 # x = x % 3
print(f"After %= 3: {x}")
x **= 3 # x = x ** 3
print(f"After **= 3: {x}")
# --- String Operations ---
print("\n--- Strings ---")
greeting = "Hello"
print(f"Greeting: {greeting}")
greeting += " World"
print(f"After += ' World': {greeting}")
repeat = "Ha"
repeat *= 3
print(f"After *= 3: {repeat}")
# --- List Operations (In-Place Modification) ---
print("\n--- Lists (In-Place) ---")
numbers = [1, 2, 3]
print(f"Before: {numbers}, id: {id(numbers)}")
numbers += [4, 5]
print(f"After += [4,5]: {numbers}, id: {id(numbers)}")
numbers *= 2
print(f"After *= 2: {numbers}")
# Compare with list + list (creates new object)
print("\n--- List + List (New Object) ---")
list1 = [1, 2, 3]
print(f"Before: {list1}, id: {id(list1)}")
list1 = list1 + [4, 5]
print(f"After + [4,5]: {list1}, id: {id(list1)}") # Different id!
# --- Practical Accumulators ---
print("\n--- Accumulator Examples ---")
# Summation
total = 0
for i in range(1, 6):
total += i
print(f"Sum of 1-5: {total}") # 15
# Factorial
factorial = 1
for i in range(1, 6):
factorial *= i
print(f"5!: {factorial}") # 120
# Counter
counter = 0
for _ in range(5): # _ is a throwaway variable
counter += 1
print(f"Counter: {counter}") # 5
# Interest calculation
balance = 1000
for year in range(3):
balance *= 1.05
print(f"Year {year+1}: ${balance:.2f}")
# --- Advanced: Conditional Augmented Assignment ---
print("\n--- Conditional ---")
score = 85
if score >= 90:
score += 5 # Bonus for high scores
print(f"Score after bonus: {score}") # 85 (no bonus applied)
# --- Dictionary Value Update ---
print("\n--- Dictionaries ---")
inventory = {"apples": 10, "bananas": 5}
inventory["apples"] += 5 # Update existing key
print(f"Inventory: {inventory}") # {'apples': 15, 'bananas': 5}
# You can even do this with new keys (after initializing)
inventory["oranges"] = 0
inventory["oranges"] += 3
print(f"After adding oranges: {inventory}") # {'apples': 15, 'bananas': 5, 'oranges': 3}
Question 1: What is the value of x after x = 5; x += 3; x *= 2?
a) 16
b) 13
c) 11
d) 18
Question 2: What is the equivalent long‑form for x //= 3?
a) x = x // 3
b) x // 3 = x
c) x = x / 3
d) x = // x 3
Question 3: Given text = "Hello", what is the result of text += " World"?
a) "HelloWorld"
b) "Hello World"
c) "WorldHello"
d) TypeError
Question 4: What happens with list1 = [1, 2]; list1 += [3, 4]?
a) list1 becomes [1, 2, 3, 4] (new object)
b) list1 becomes [1, 2, 3, 4] (same object, modified in‑place)
c) list1 becomes [1, 2]
d) TypeError
Question 5: What is the output of x = 10; x /= 3; print(x)?
a) 3
b) 3.3333333333333335
c) 3.0
d) 4
Question 6: What is the output of:
a = [1, 2]
b = a
a += [3]
print(b)
a) [1, 2]
b) [1, 2, 3]
c) [3]
d) Error
Question 7: What is the difference between x += y for an integer vs. a list?
a) No difference
b) For integers, it creates a new object; for lists, it modifies in‑place
c) For lists, it creates a new object; for integers, it modifies in‑place
d) Both create a new object
Question 8: What is total after total = 1; for i in range(1, 4): total *= i?
a) 6
b) 3
c) 1
d) 0
Question 9: Which is not a valid augmented assignment operator?
a) +=
b) -=
c) ++=
d) *=
Question 10: What happens with x += 5 if x is not defined?
a) x is created with value 5
b) NameError
c) SyntaxError
d) TypeError
Exercise 1: Convert to Augmented Assignment
Convert the following standard assignments to augmented:
x = x + 5, y = y * 2, total = total / 3, count = count - 1, balance = balance * 1.1, text = text + "!", numbers = numbers + [10], value = value ** 2.
Exercise 2: Summation Calculator
Ask the user for how many numbers, then use a loop to accumulate the sum with += and print the sum and average.
Exercise 3: String Builder
Start with an empty string, ask for 5 words, append each with a space, and print the final sentence.
Exercise 4: Interest Calculator
Write a program that:
*= to calculate the balance each year."""
INTEREST CALCULATOR
Calculates compound interest year by year using augmented assignment
"""
print("=" * 60)
print("INTEREST CALCULATOR")
print("=" * 60)
# --- Get user input with error handling ---
print("\nEnter your investment details:")
try:
principal = float(input(" Initial investment amount: $"))
if principal < 0:
print(" Warning: Investment amount should be positive.")
principal = abs(principal)
rate = float(input(" Annual interest rate (as %): "))
if rate < 0:
print(" Warning: Interest rate should be positive.")
rate = abs(rate)
years = int(input(" Number of years: "))
if years < 0:
print(" Warning: Years should be positive.")
years = abs(years)
except ValueError:
print("\nInvalid input! 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"Initial Investment: ${principal:,.2f}")
print(f"Interest Rate: {rate}%")
print(f"Number of Years: {years}")
# --- Calculate balance each year using a loop and *= ---
print("\n" + "-" * 60)
print("YEAR-BY-YEAR GROWTH")
print("-" * 60)
# Initialize balance with the principal
balance = principal
# Print header
print(f"{'Year':>6} | {'Balance':>12} | {'Interest Earned':>15}")
print("-" * 60)
total_interest = 0
# Loop through each year
for year in range(1, years + 1):
# Calculate interest for this year
interest_this_year = balance * (rate / 100)
# Use *= to add interest to the balance
balance *= (1 + rate / 100) # balance = balance * (1 + rate/100)
# Accumulate total interest
total_interest += interest_this_year
# Print year's balance
print(f"{year:>6} | ${balance:>11,.2f} | ${interest_this_year:>14,.2f}")
print("-" * 60)
# --- Print final summary ---
print("\n" + "-" * 60)
print("FINAL SUMMARY")
print("-" * 60)
print(f"Initial Investment: ${principal:>11,.2f}")
print(f"Final Balance: ${balance:>11,.2f}")
print(f"Total Interest Earned: ${total_interest:>11,.2f}")
# Calculate and print additional metrics
total_growth = balance - principal
growth_percentage = (total_growth / principal) * 100
print(f"Total Growth: ${total_growth:>11,.2f} ({growth_percentage:.1f}%)")
# --- Challenge: Verify using formula ---
print("\n" + "-" * 60)
print("VERIFICATION (Using Compound Interest Formula)")
print("-" * 60)
# Formula: FV = P * (1 + r/100)^n
future_value_formula = principal * (1 + rate / 100) ** years
interest_formula = future_value_formula - principal
print(f"Formula Future Value: ${future_value_formula:>11,.2f}")
print(f"Formula Interest: ${interest_formula:>11,.2f}")
print(f"Loop method matches? {'✅ Yes' if abs(balance - future_value_formula) < 0.01 else '❌ No'}")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • Use `balance *= (1 + rate/100)` to compound interest annually")
print(" • Augmented assignment `*=` modifies the variable in-place")
print(" • The loop method shows year-by-year growth")
print(" • The formula `P * (1 + r/100)^n` gives the same result")
print(" • Total interest = Final Balance - Principal")
print("=" * 60)
Sample Output:
============================================================
INTEREST CALCULATOR
============================================================
Enter your investment details:
Initial investment amount: $1000
Annual interest rate (as %): 5
Number of years: 10
------------------------------------------------------------
INVESTMENT DETAILS
------------------------------------------------------------
Initial Investment: $1,000.00
Interest Rate: 5.0%
Number of Years: 10
------------------------------------------------------------
YEAR-BY-YEAR GROWTH
------------------------------------------------------------
Year | Balance | Interest Earned
------------------------------------------------------------
1 | $1,050.00 | $50.00
2 | $1,102.50 | $52.50
3 | $1,157.63 | $55.13
4 | $1,215.51 | $57.88
5 | $1,276.28 | $60.78
6 | $1,340.10 | $63.81
7 | $1,407.10 | $67.01
8 | $1,477.46 | $70.35
9 | $1,551.33 | $73.87
10 | $1,628.89 | $77.56
------------------------------------------------------------
------------------------------------------------------------
FINAL SUMMARY
------------------------------------------------------------
Initial Investment: $1,000.00
Final Balance: $1,628.89
Total Interest Earned: $628.89
Total Growth: $628.89 (62.9%)
------------------------------------------------------------
VERIFICATION (Using Compound Interest Formula)
------------------------------------------------------------
Formula Future Value: $1,628.89
Formula Interest: $628.89
Loop method matches? ✅ Yes
============================================================
KEY TAKEAWAYS
============================================================
• Use `balance *= (1 + rate/100)` to compound interest annually
• Augmented assignment `*=` modifies the variable in-place
• The loop method shows year-by-year growth
• The formula `P * (1 + r/100)^n` gives the same result
• Total interest = Final Balance - Principal
============================================================
Explanation:
balance *= (1 + rate / 100) – This is equivalent to balance = balance * (1 + rate / 100). It multiplies the balance by the growth factor each year.
Year-by-year calculation – The loop shows how the balance grows each year, with interest earned on the new balance.
Compound interest – Interest is calculated on the current balance (including previous interest).
Verification – The loop result matches the compound interest formula.
Exercise 5: List Builder with Augmented Assignment
Write a program that:
squares = [].+= (with the square as a single-element list).*= 2 to double all elements in the list and print the doubled list."""
LIST BUILDER WITH AUGMENTED ASSIGNMENT
Demonstrates using += and *= with lists
"""
print("=" * 60)
print("LIST BUILDER WITH AUGMENTED ASSIGNMENT")
print("=" * 60)
# --- Step 1: Create empty list ---
squares = []
print(f"Step 1 - squares initialized: {squares}")
# --- Step 2: Build list using += ---
print("\n" + "-" * 60)
print("BUILDING SQUARES LIST (using +=)")
print("-" * 60)
for i in range(1, 11):
# Calculate square
square = i ** 2
# Append using += (adds a single-element list)
squares += [square]
# Show progress
print(f" i={i:>2}, square={square:>3}, squares={squares}")
print("\n" + "-" * 60)
print("FINAL SQUARES LIST")
print("-" * 60)
print(f"Squares: {squares}")
print(f"Length: {len(squares)}")
print(f"ID: {id(squares)}")
# --- Step 3: Demonstrate different ways to append ---
print("\n" + "-" * 60)
print("COMPARISON OF APPEND METHODS")
print("-" * 60)
# Method 1: Using += with single-element list
print("\nMethod 1: squares += [value]")
test_list1 = []
for i in range(1, 6):
test_list1 += [i]
print(f" Result: {test_list1}")
# Method 2: Using append() method
print("\nMethod 2: squares.append(value)")
test_list2 = []
for i in range(1, 6):
test_list2.append(i)
print(f" Result: {test_list2}")
# Method 3: Using extend() method
print("\nMethod 3: squares.extend([value])")
test_list3 = []
for i in range(1, 6):
test_list3.extend([i])
print(f" Result: {test_list3}")
print("\nAll three methods produce the same result!")
# --- Step 4: Advanced - Double all elements using *= ---
print("\n" + "-" * 60)
print("ADVANCED: DOUBLING ALL ELEMENTS (using *=)")
print("-" * 60)
# Start from the original squares list
doubled = squares[:] # Make a copy
print(f"Before doubling: {doubled}")
# Use *= to double all elements
doubled *= 2
print(f"After doubling: {doubled}")
print("\n" + "-" * 60)
print("ANALYSIS")
print("-" * 60)
print(f"Original squares: {squares}")
print(f"Doubled version: {doubled}")
print(f"Original length: {len(squares)}")
print(f"Doubled length: {len(doubled)}")
# --- Step 5: More advanced list operations with *= ---
print("\n" + "-" * 60)
print("MORE LIST OPERATIONS WITH *=")
print("-" * 60)
# Example 1: Repeat a list
base_list = [1, 2, 3]
print(f"Base list: {base_list}")
base_list *= 3
print(f"Repeated 3 times: {base_list}")
# Example 2: Create pattern
pattern = ["*"]
pattern *= 5
print(f"Pattern: {pattern}")
print(f"Pattern as string: {''.join(pattern)}")
# Example 3: Mixed data types
mixed = [1, "a", True]
mixed *= 2
print(f"Mixed list doubled: {mixed}")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • `list += [value]` appends a single element (like `.append()`)")
print(" • `list += [value1, value2]` extends the list with multiple elements")
print(" • `list *= n` duplicates the entire list n times")
print(" • `+=` and `*=` modify the list in-place (no new object created)")
print(" • All these operations work on mutable sequences like lists")
print("=" * 60)
Sample Output:
============================================================
LIST BUILDER WITH AUGMENTED ASSIGNMENT
============================================================
Step 1 - squares initialized: []
------------------------------------------------------------
BUILDING SQUARES LIST (using +=)
------------------------------------------------------------
i= 1, square= 1, squares=[1]
i= 2, square= 4, squares=[1, 4]
i= 3, square= 9, squares=[1, 4, 9]
i= 4, square= 16, squares=[1, 4, 9, 16]
i= 5, square= 25, squares=[1, 4, 9, 16, 25]
i= 6, square= 36, squares=[1, 4, 9, 16, 25, 36]
i= 7, square= 49, squares=[1, 4, 9, 16, 25, 36, 49]
i= 8, square= 64, squares=[1, 4, 9, 16, 25, 36, 49, 64]
i= 9, square= 81, squares=[1, 4, 9, 16, 25, 36, 49, 64, 81]
i=10, square=100, squares=[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
------------------------------------------------------------
FINAL SQUARES LIST
------------------------------------------------------------
Squares: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Length: 10
ID: 140734567890123
------------------------------------------------------------
COMPARISON OF APPEND METHODS
------------------------------------------------------------
Method 1: squares += [value]
Result: [1, 2, 3, 4, 5]
Method 2: squares.append(value)
Result: [1, 2, 3, 4, 5]
Method 3: squares.extend([value])
Result: [1, 2, 3, 4, 5]
All three methods produce the same result!
------------------------------------------------------------
ADVANCED: DOUBLING ALL ELEMENTS (using *=)
------------------------------------------------------------
Before doubling: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
After doubling: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
------------------------------------------------------------
ANALYSIS
------------------------------------------------------------
Original squares: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Doubled version: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Original length: 10
Doubled length: 20
------------------------------------------------------------
MORE LIST OPERATIONS WITH *=
------------------------------------------------------------
Base list: [1, 2, 3]
Repeated 3 times: [1, 2, 3, 1, 2, 3, 1, 2, 3]
Pattern: ['*', '*', '*', '*', '*']
Pattern as string: *****
Mixed list doubled: [1, 'a', True, 1, 'a', True]
============================================================
KEY TAKEAWAYS
============================================================
• `list += [value]` appends a single element (like `.append()`)
• `list += [value1, value2]` extends the list with multiple elements
• `list *= n` duplicates the entire list n times
• `+=` and `*=` modify the list in-place (no new object created)
• All these operations work on mutable sequences like lists
============================================================
Explanation:
squares += [square] – Appends a single element to the list. This works because += on a list extends it by the elements of the right-hand list.
Multiple ways to append:
+= [value] – Concise and works like .extend([value]).append(value) – The standard method.extend([value]) – More explicitdoubled *= 2 – Doubles the list by duplicating all elements. This is equivalent to doubled = doubled * 2.
In-place modification – Both += and *= modify the list object in-place (no new list created).
Key Difference:
squares += [square] modifies the original list.squares = squares + [square] would create a new list.Exercise 6: Inventory Management
Write a program that:
inventory = {"apples": 10, "bananas": 5, "oranges": 3}.-=).+= to add 4 grapes."""
INVENTORY MANAGEMENT
Demonstrates augmented assignment with dictionaries
"""
print("=" * 60)
print("INVENTORY MANAGEMENT")
print("=" * 60)
# --- Step 1: Create the initial inventory ---
inventory = {"apples": 10, "bananas": 5, "oranges": 3}
print("\nInitial Inventory:")
print_inventory(inventory)
# --- Step 2: Update inventory using augmented assignments ---
print("\n" + "-" * 60)
print("UPDATING INVENTORY")
print("-" * 60)
# Add 2 apples (using +=)
print("\n1. Adding 2 apples...")
inventory["apples"] += 2
print(f" apples: {inventory['apples']}")
# Remove 1 banana (using -=)
print("\n2. Removing 1 banana...")
inventory["bananas"] -= 1
print(f" bananas: {inventory['bananas']}")
# Double the number of oranges (using *=)
print("\n3. Doubling oranges...")
inventory["oranges"] *= 2
print(f" oranges: {inventory['oranges']}")
# --- Step 3: Print the updated inventory ---
print("\n" + "-" * 60)
print("UPDATED INVENTORY")
print("-" * 60)
print_inventory(inventory)
# --- Step 4: Bonus - Add a new item "grapes" ---
print("\n" + "-" * 60)
print("BONUS: ADDING NEW ITEM")
print("-" * 60)
print("\n4. Adding new item 'grapes'...")
inventory["grapes"] = 0 # Initialize with 0
print(f" After initialization: grapes = {inventory['grapes']}")
# Use += to add 4 grapes
inventory["grapes"] += 4
print(f" After adding 4 grapes: grapes = {inventory['grapes']}")
# --- Step 5: Final inventory ---
print("\n" + "=" * 60)
print("FINAL INVENTORY")
print("=" * 60)
print_inventory(inventory)
# --- Step 6: Additional operations ---
print("\n" + "-" * 60)
print("ADDITIONAL INVENTORY OPERATIONS")
print("-" * 60)
# Example of updating with other operations
print("\nPerforming more updates:")
inventory = {"apples": 10, "bananas": 5, "oranges": 3} # Reset
# Multiple updates
print(f"Starting inventory: {inventory}")
inventory["apples"] += 3
inventory["bananas"] -= 2
inventory["oranges"] **= 2 # Square the oranges
print(f"After operations: {inventory}")
# Example of %= (modulo)
inventory["apples"] %= 5
print(f"After apples %= 5: {inventory}")
# Example of //= (floor division)
inventory["bananas"] //= 2
print(f"After bananas //= 2: {inventory}")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • `inventory['key'] += value` updates a dictionary value in-place")
print(" • All augmented assignment operators work with dictionary values")
print(" • You must initialize a key before using `+=` (or other operators)")
print(" • To add a new item: set it to 0 first, then use `+=`")
print(" • Dictionary values are mutable if they are mutable objects")
print("=" * 60)
Helper Function:
def print_inventory(inventory):
"""Helper function to print inventory nicely."""
print("-" * 40)
print(f"{'Item':<12} {'Quantity':>10}")
print("-" * 40)
for item, quantity in inventory.items():
print(f"{item:<12} {quantity:>10}")
print("-" * 40)
total = sum(inventory.values())
print(f"{'TOTAL':<12} {total:>10}")
print("-" * 40)
Sample Output:
============================================================
INVENTORY MANAGEMENT
============================================================
Initial Inventory:
--------------------------------------------
Item Quantity
--------------------------------------------
apples 10
bananas 5
oranges 3
--------------------------------------------
TOTAL 18
--------------------------------------------
------------------------------------------------------------
UPDATING INVENTORY
------------------------------------------------------------
1. Adding 2 apples...
apples: 12
2. Removing 1 banana...
bananas: 4
3. Doubling oranges...
oranges: 6
------------------------------------------------------------
UPDATED INVENTORY
------------------------------------------------------------
--------------------------------------------
Item Quantity
--------------------------------------------
apples 12
bananas 4
oranges 6
--------------------------------------------
TOTAL 22
--------------------------------------------
------------------------------------------------------------
BONUS: ADDING NEW ITEM
------------------------------------------------------------
4. Adding new item 'grapes'...
After initialization: grapes = 0
After adding 4 grapes: grapes = 4
============================================================
FINAL INVENTORY
============================================================
--------------------------------------------
Item Quantity
--------------------------------------------
apples 12
bananas 4
oranges 6
grapes 4
--------------------------------------------
TOTAL 26
--------------------------------------------
------------------------------------------------------------
ADDITIONAL INVENTORY OPERATIONS
------------------------------------------------------------
Performing more updates:
Starting inventory: {'apples': 10, 'bananas': 5, 'oranges': 3}
After operations: {'apples': 13, 'bananas': 3, 'oranges': 9}
After apples %= 5: {'apples': 3, 'bananas': 3, 'oranges': 9}
After bananas //= 2: {'apples': 3, 'bananas': 1, 'oranges': 9}
============================================================
KEY TAKEAWAYS
============================================================
• `inventory['key'] += value` updates a dictionary value in-place
• All augmented assignment operators work with dictionary values
• You must initialize a key before using `+=` (or other operators)
• To add a new item: set it to 0 first, then use `+=`
• Dictionary values are mutable if they are mutable objects
============================================================
Explanation:
Dictionary Value Updates:
inventory["apples"] += 2 – Equivalent to inventory["apples"] = inventory["apples"] + 2+= to work (otherwise you get a KeyError)Adding a New Item:
inventory["grapes"] = 0inventory["grapes"] += 4All Augmented Operators Work:
+=, -=, *=, /=, //=, %=, **=In-place Modification:
Common Pitfall:
# WRONG - This will cause a KeyError
inventory = {"apples": 10}
inventory["bananas"] += 5 # KeyError! 'bananas' doesn't exist
# CORRECT - Initialize first
inventory["bananas"] = 0
inventory["bananas"] += 5
# OR use a more advanced approach (beyond this unit)
inventory["bananas"] = inventory.get("bananas", 0) + 5
Key Takeaways:
+=, -=, etc. (unlike assigning a new key with =).0 before using +=.Question 1 (Conceptual – Mutability and Augmented Assignments):
Explain the difference between list_a += list_b and list_a = list_a + list_b. When would you prefer one over the other?
Question 2 (Code Analysis – Predict Output):
What is printed and why?
a = [1, 2, 3]
b = a
a = a + [4, 5]
b += [6]
print(a)
print(b)
Question 3 (Real-World Application – Shopping Cart):
Write a complete program that simulates a shopping cart:
cart = [] and a total = 0.0.+= to add the item to the cart (as a tuple (item, price)).+= to add the price to the total.*= if the total exceeds $100."""
SHOPPING CART SIMULATOR
Demonstrates augmented assignment with lists and totals
"""
print("=" * 60)
print("SHOPPING CART SIMULATOR")
print("=" * 60)
# --- Step 1: Initialize empty cart and total ---
cart = []
total = 0.0
print("\nEnter items for your shopping cart.")
print("Type 'done' when finished.\n")
# --- Step 2-5: Loop to get items ---
item_count = 0
while True:
# Get item name
item = input(f"Item #{item_count + 1} name (or 'done'): ").strip()
# Check if user wants to stop
if item.lower() == 'done':
break
# Get item price
try:
price = float(input(f" Price for '{item}': $"))
if price < 0:
print(" Price cannot be negative. Please try again.")
continue
except ValueError:
print(" Invalid price. Please enter a number.")
continue
# --- Step 4: Add item to cart using += ---
# cart += [(item, price)] # Adds a single tuple as a list element
# Alternative: cart.append((item, price))
cart += [(item, price)]
# --- Step 5: Add price to total using += ---
total += price
item_count += 1
print(f" Added: {item} (${price:.2f})")
print(f" Cart total: ${total:.2f}\n")
# --- Step 6: Display the cart and total ---
print("\n" + "=" * 60)
print("SHOPPING CART SUMMARY")
print("=" * 60)
if not cart:
print("\nYour cart is empty.")
else:
print("\nItems in your cart:")
print("-" * 50)
print(f"{'Item':<30} {'Price':>10}")
print("-" * 50)
for item, price in cart:
print(f"{item:<30} ${price:>9.2f}")
print("-" * 50)
# --- Step 7: Apply discount if total exceeds $100 ---
original_total = total
discount_applied = False
if total > 100:
print(f"Subtotal: ${total:>9.2f}")
print("🎉 You qualify for a 10% discount!")
# Apply discount using *=
discount = total * 0.10
total *= 0.90 # total = total * 0.90 (10% discount)
discount_applied = True
print(f"Discount (10%): -${discount:>8.2f}")
print("-" * 50)
print(f"TOTAL: ${total:>9.2f}")
if discount_applied:
print(f"\nYou saved ${original_total - total:.2f} today!")
print("\n" + "=" * 60)
print("CART STATISTICS")
print("=" * 60)
# Additional statistics
print(f"Total items: {len(cart)}")
print(f"Original total: ${original_total:>9.2f}")
print(f"Final total: ${total:>9.2f}")
# Find most expensive item (without max())
if cart:
most_expensive = cart[0]
for item, price in cart:
if price > most_expensive[1]:
most_expensive = (item, price)
print(f"Most expensive: {most_expensive[0]} (${most_expensive[1]:.2f})")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • `cart += [(item, price)]` adds a tuple to the list")
print(" • `total += price` accumulates the running total")
print(" • `total *= 0.90` applies a 10% discount")
print(" • Augmented assignment works with lists (extend) and numbers")
print(" • Always validate user input to prevent errors")
print("=" * 60)
Sample Output (with discount):
============================================================
SHOPPING CART SIMULATOR
============================================================
Enter items for your shopping cart.
Type 'done' when finished.
Item #1 name (or 'done'): Laptop
Price for 'Laptop': $999.99
Added: Laptop ($999.99)
Cart total: $999.99
Item #2 name (or 'done'): Mouse
Price for 'Mouse': $29.99
Added: Mouse ($29.99)
Cart total: $1029.98
Item #3 name (or 'done'): done
============================================================
SHOPPING CART SUMMARY
============================================================
Items in your cart:
--------------------------------------------------
Item Price
--------------------------------------------------
Laptop $999.99
Mouse $29.99
--------------------------------------------------
Subtotal: $1029.98
🎉 You qualify for a 10% discount!
Discount (10%): -$103.00
--------------------------------------------------
TOTAL: $926.98
You saved $103.00 today!
============================================================
CART STATISTICS
============================================================
Total items: 2
Original total: $1029.98
Final total: $926.98
Most expensive: Laptop ($999.99)
============================================================
KEY TAKEAWAYS
============================================================
• `cart += [(item, price)]` adds a tuple to the list
• `total += price` accumulates the running total
• `total *= 0.90` applies a 10% discount
• Augmented assignment works with lists (extend) and numbers
• Always validate user input to prevent errors
============================================================
Sample Output (no discount):
============================================================
SHOPPING CART SIMULATOR
============================================================
Enter items for your shopping cart.
Type 'done' when finished.
Item #1 name (or 'done'): Apple
Price for 'Apple': $1.50
Added: Apple ($1.50)
Cart total: $1.50
Item #2 name (or 'done'): Banana
Price for 'Banana': $0.75
Added: Banana ($0.75)
Cart total: $2.25
Item #3 name (or 'done'): done
============================================================
SHOPPING CART SUMMARY
============================================================
Items in your cart:
--------------------------------------------------
Item Price
--------------------------------------------------
Apple $1.50
Banana $0.75
--------------------------------------------------
TOTAL: $2.25
============================================================
CART STATISTICS
============================================================
Total items: 2
Original total: $2.25
Final total: $2.25
Most expensive: Apple ($1.50)
============================================================
KEY TAKEAWAYS
============================================================
• `cart += [(item, price)]` adds a tuple to the list
• `total += price` accumulates the running total
• `total *= 0.90` applies a 10% discount
• Augmented assignment works with lists (extend) and numbers
• Always validate user input to prevent errors
============================================================
Explanation:
cart += [(item, price)] – This extends the list by adding a single tuple. It's equivalent to cart.append((item, price)).
total += price – Adds the price to the running total.
total *= 0.90 – Applies a 10% discount (multiplies by 0.90). This is only applied if the condition total > 100 is true.
Data Structure – Each item is stored as a tuple (name, price) inside the list.
Loop Control – while True with break when "done" is entered.
Question 4 (Performance Consideration – String Building):
What is the issue with using += to build a long string in a loop (e.g., for i in range(10000): result += str(i))? Research and explain why this is inefficient. What is the recommended alternative?
"""
STRING BUILDING PERFORMANCE COMPARISON
Demonstrates why using += in a loop is inefficient for strings
"""
import time
print("=" * 60)
print("STRING BUILDING PERFORMANCE COMPARISON")
print("=" * 60)
# --- The Problem: Using += in a loop ---
print("\n" + "-" * 60)
print("METHOD 1: Using += (Inefficient)")
print("-" * 60)
print("\nWhat happens when you use `result += str(i)` in a loop?")
print("-" * 40)
# Explanation with a small example
result = ""
for i in range(5):
result += str(i)
print(f" Step {i+1}: result = '{result}' (creates a new string)")
print("\nAt each step, a NEW string is created and the old one is discarded!")
print("\n" + "-" * 60)
print("THE PROBLEM EXPLAINED")
print("-" * 60)
print("""
Strings in Python are IMMUTABLE (cannot be changed).
When you do `result += str(i)`, Python:
1. Reads the current value of 'result'
2. Creates a NEW string with the concatenated result
3. Assigns 'result' to point to the new string
4. The old string is garbage-collected
This creates many intermediate strings. For n items:
• 1st iteration: creates 1 string
• 2nd iteration: creates 1 string
• ...
• nth iteration: creates 1 string
Total: n strings are created, but only the final one is needed!
Time complexity: O(n²) because each concatenation copies the entire string.
""")
# --- Performance comparison ---
print("\n" + "-" * 60)
print("PERFORMANCE COMPARISON")
print("-" * 60)
print("\nTesting with 10,000 iterations:")
# Method 1: Using += (inefficient)
start_time = time.time()
result_append = ""
for i in range(10000):
result_append += str(i)
time_append = time.time() - start_time
print(f"\nMethod 1 (+=): {time_append:.6f} seconds")
# Method 2: Using join() (efficient)
start_time = time.time()
parts = []
for i in range(10000):
parts.append(str(i))
result_join = "".join(parts)
time_join = time.time() - start_time
print(f"Method 2 (join()): {time_join:.6f} seconds")
# Method 3: Using join() with generator (most efficient)
start_time = time.time()
result_generator = "".join(str(i) for i in range(10000))
time_generator = time.time() - start_time
print(f"Method 3 (generator): {time_generator:.6f} seconds")
if time_append > 0:
speedup = time_append / time_join
print(f"\n✅ join() is {speedup:.1f}x faster than using +=!")
# --- Demonstration with a larger test ---
print("\n" + "-" * 60)
print("TESTING WITH DIFFERENT SIZES")
print("-" * 60)
def test_string_building(size, method='join'):
"""Test string building with different methods."""
if method == 'append':
result = ""
for i in range(size):
result += str(i)
return result
elif method == 'join':
return "".join(str(i) for i in range(size))
elif method == 'list_join':
parts = []
for i in range(size):
parts.append(str(i))
return "".join(parts)
# Test with different sizes
sizes = [100, 1000, 5000, 10000]
print(f"{'Size':>8} | {'+= Time':>12} | {'join() Time':>12} | {'Speedup':>10}")
print("-" * 55)
for size in sizes:
# Time the += method
start = time.time()
test_string_building(size, 'append')
time_append = time.time() - start
# Time the join() method
start = time.time()
test_string_building(size, 'join')
time_join = time.time() - start
speedup = time_append / time_join if time_join > 0 else 0
print(f"{size:>8} | {time_append:>11.6f}s | {time_join:>11.6f}s | {speedup:>9.1f}x")
print("\n" + "-" * 60)
print("WHY THIS HAPPENS")
print("-" * 60)
print("""
The += method has O(n²) time complexity because:
• Each concatenation copies the entire existing string
• The cost grows with the string length
• For n = 10,000, this means 100 million operations!
The join() method has O(n) time complexity because:
• It first collects all strings in a list
• It pre-calculates the total length
• It allocates memory ONCE for the final string
• It copies each string exactly ONCE
This makes join() MUCH faster for large string concatenations.
""")
print("\n" + "=" * 60)
print("THE RECOMMENDED ALTERNATIVE")
print("=" * 60)
print("""
✅ USE `''.join()` for concatenating multiple strings!
The recommended pattern is:
```python
parts = []
for i in range(10000):
parts.append(str(i))
result = ''.join(parts)
Or more concisely:
result = ''.join(str(i) for i in range(10000))
This is the standard Pythonic way to build strings efficiently. """)
print("\n" + "-" 60) print("EXCEPTIONS") print("-" 60)
print(""" There are a few cases where using += is acceptable:
Example where += is fine:
greeting = "Hello"
greeting += " World"
greeting += "!"
But for loops with many iterations, always use join()! """)
print("\n" + "=" 60)
print("KEY TAKEAWAYS")
print("=" 60)
print(" • Strings are immutable – each += creates a new string")
print(" • += in a loop has O(n²) time complexity")
print(" • Use ''.join(list) for efficient string concatenation")
print(" • join() allocates memory once and copies each string once")
print(" • For small strings or few concatenations, += is acceptable")
print("=" * 60)
**Sample Output:**
result += str(i) in a loop?Step 1: result = '0' (creates a new string) Step 2: result = '01' (creates a new string) Step 3: result = '012' (creates a new string) Step 4: result = '0123' (creates a new string) Step 5: result = '01234' (creates a new string)
At each step, a NEW string is created and the old one is discarded!
Strings in Python are IMMUTABLE (cannot be changed).
When you do result += str(i), Python:
This creates many intermediate strings. For n items: • 1st iteration: creates 1 string • 2nd iteration: creates 1 string • ... • nth iteration: creates 1 string
Total: n strings are created, but only the final one is needed!
Time complexity: O(n²) because each concatenation copies the entire string.
Testing with 10,000 iterations:
Method 1 (+=): 0.023456 seconds Method 2 (join()): 0.001234 seconds Method 3 (generator): 0.001123 seconds
✅ join() is 19.0x faster than using +=!
Size | += Time | join() Time | Speedup
100 | 0.000234s | 0.000045s | 5.2x
1000 | 0.002345s | 0.000123s | 19.1x
5000 | 0.012345s | 0.000456s | 27.1x
10000 | 0.045678s | 0.000789s | 57.9x
The += method has O(n²) time complexity because: • Each concatenation copies the entire existing string • The cost grows with the string length • For n = 10,000, this means 100 million operations!
The join() method has O(n) time complexity because: • It first collects all strings in a list • It pre-calculates the total length • It allocates memory ONCE for the final string • It copies each string exactly ONCE
This makes join() MUCH faster for large string concatenations.
✅ USE ''.join() for concatenating multiple strings!
The recommended pattern is:
parts = []
for i in range(10000):
parts.append(str(i))
result = ''.join(parts)
Or more concisely:
result = ''.join(str(i) for i in range(10000))
This is the standard Pythonic way to build strings efficiently.
+= creates a new string
• += in a loop has O(n²) time complexity
• Use ''.join(list) for efficient string concatenation
• join() allocates memory once and copies each string once
• For small strings or few concatenations, += is acceptable
**Explanation:**
**The Problem:**
1. **Strings are immutable** – They cannot be modified in-place.
2. **`+=` creates new strings** – Each concatenation creates a new string object.
3. **O(n²) complexity** – Each concatenation copies the entire growing string.
4. **Memory waste** – Many intermediate strings are created and discarded.
**The Solution:**
1. **`''.join(list)`** – The standard Python way to build strings.
2. **O(n) complexity** – Allocates memory once and copies each string once.
3. **Memory efficient** – No intermediate strings created.
4. **Faster** – Significantly faster for large operations.
**When to Use Each:**
- **Small strings** – `+=` is acceptable (e.g., building a short message).
- **Large strings or loops** – Always use `join()`.
- **One-off concatenation** – `+=` is fine.
- **Many concatenations** – Use `join()` for performance.
</details>
**Question 5 (Challenge – Stats Calculator):**
Write a program that:
1. Creates a list `grades = [85, 92, 78, 90, 88, 76, 95]`.
2. Calculates and prints:
- The sum of all grades (use a loop with `+=`).
- The average (use `/=` or `/`).
- The highest grade (use a loop and a conditional, no `max()` function).
- The lowest grade (use a loop and a conditional, no `min()` function).
3. **Advanced:** Calculate the standard deviation using the formula `sqrt(sum((x - mean)**2) / n)`. You'll need to use `**=` and `+=` in loops.
<details><summary>Sample Answer</summary>
```python
"""
STATS CALCULATOR
Calculates statistics using loops and augmented assignment
"""
import math
print("=" * 60)
print("STATS CALCULATOR")
print("=" * 60)
# --- Step 1: Create the grades list ---
grades = [85, 92, 78, 90, 88, 76, 95]
print(f"\nGrades: {grades}")
print(f"Number of grades: {len(grades)}")
print("\n" + "-" * 60)
print("BASIC STATISTICS")
print("-" * 60)
# --- Step 2a: Calculate sum using loop with += ---
sum_grades = 0
for grade in grades:
sum_grades += grade
print(f"Sum: {sum_grades}")
# --- Step 2b: Calculate average using /= ---
avg = sum_grades / len(grades)
print(f"Average: {avg:.2f}")
# --- Step 2c: Find highest grade (no max()) ---
highest = grades[0] # Start with first element
for grade in grades:
if grade > highest:
highest = grade
print(f"Highest: {highest}")
# --- Step 2d: Find lowest grade (no min()) ---
lowest = grades[0] # Start with first element
for grade in grades:
if grade < lowest:
lowest = grade
print(f"Lowest: {lowest}")
print("\n" + "-" * 60)
print("ADDITIONAL STATISTICS")
print("-" * 60)
# --- Additional statistics using built-in functions ---
print(f"\nUsing built-in functions (for verification):")
print(f" sum(grades): {sum(grades)}")
print(f" max(grades): {max(grades)}")
print(f" min(grades): {min(grades)}")
print(f" len(grades): {len(grades)}")
print(f" Average: {sum(grades) / len(grades):.2f}")
# --- Step 3: Advanced - Calculate standard deviation ---
print("\n" + "-" * 60)
print("ADVANCED: STANDARD DEVIATION")
print("-" * 60)
# Formula: σ = sqrt(Σ(x - mean)² / n)
# Step 1: Calculate sum of squared differences using += and **=
sum_squared_diff = 0
for grade in grades:
diff = grade - avg
diff_squared = diff ** 2 # Using ** operator
sum_squared_diff += diff_squared
# Or use **= with a variable
# diff = grade - avg
# diff **= 2
# sum_squared_diff += diff
print(f"\nStep-by-step calculation:")
print(f" Mean: {avg:.2f}")
print(f" Sum of squared differences: {sum_squared_diff:.2f}")
# Step 2: Calculate variance
variance = sum_squared_diff / len(grades)
print(f" Variance: {variance:.2f}")
# Step 3: Calculate standard deviation (square root)
std_dev = math.sqrt(variance)
print(f" Standard Deviation: {std_dev:.2f}")
# --- Alternative: Using a single loop with **= ---
print("\n" + "-" * 60)
print("ALTERNATIVE CALCULATION")
print("-" * 60)
# Using **= within the loop
sum_sq_diff = 0
for grade in grades:
diff = grade - avg
diff **= 2 # Square the difference
sum_sq_diff += diff
std_dev_alt = math.sqrt(sum_sq_diff / len(grades))
print(f"Using **= in loop:")
print(f" Standard Deviation: {std_dev_alt:.2f}")
print(f" Matches previous result? {'✅ Yes' if abs(std_dev - std_dev_alt) < 0.001 else '❌ No'}")
# --- More advanced statistics ---
print("\n" + "-" * 60)
print("ADVANCED STATISTICS")
print("-" * 60)
# Sort grades (using sorted)
sorted_grades = sorted(grades)
print(f"Sorted grades: {sorted_grades}")
# Median
n = len(grades)
if n % 2 == 1:
median = sorted_grades[n // 2]
else:
median = (sorted_grades[n // 2 - 1] + sorted_grades[n // 2]) / 2
print(f"Median: {median}")
# Range
range_val = highest - lowest
print(f"Range: {range_val}")
# Grade distribution
print("\nGrade Distribution:")
def get_letter(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
# Count letter grades
letter_counts = {}
for grade in grades:
letter = get_letter(grade)
letter_counts[letter] = letter_counts.get(letter, 0) + 1
for letter in ['A', 'B', 'C', 'D', 'F']:
count = letter_counts.get(letter, 0)
if count > 0:
print(f" {letter}: {count} grade(s)")
# --- Step-by-step standard deviation calculation with explanations ---
print("\n" + "-" * 60)
print("STANDARD DEVIATION STEP-BY-STEP")
print("-" * 60)
print("\nDetailed calculation of standard deviation:")
print(f"Grades: {grades}")
print(f"Mean: {avg:.2f}\n")
print("Step 1: Calculate squared differences (x - mean)²")
print(f"{'Grade':>8} | {'x - mean':>12} | {'(x - mean)²':>14}")
print("-" * 45)
sum_sq = 0
for grade in grades:
diff = grade - avg
diff_sq = diff ** 2
sum_sq += diff_sq
print(f"{grade:>8} | {diff:>11.2f} | {diff_sq:>13.2f}")
print("-" * 45)
print(f"{'TOTAL':>8} | {'':>12} | {sum_sq:>14.2f}")
print(f"\nStep 2: Variance = sum_sq / n = {sum_sq} / {len(grades)} = {sum_sq / len(grades):.2f}")
print(f"Step 3: Standard Deviation = sqrt(Variance) = sqrt({sum_sq / len(grades):.2f}) = {math.sqrt(sum_sq / len(grades)):.2f}")
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • Use `sum_var += value` to accumulate totals in loops")
print(" • Use `value **= 2` to square a value in-place")
print(" • Use `value /= n` to divide and assign")
print(" • Manual loops can replace built-in functions like sum(), max(), min()")
print(" • Augmented assignment makes code more concise")
print(" • Standard deviation measures the spread of data around the mean")
print("=" * 60)
Sample Output:
============================================================
STATS CALCULATOR
============================================================
Grades: [85, 92, 78, 90, 88, 76, 95]
Number of grades: 7
------------------------------------------------------------
BASIC STATISTICS
------------------------------------------------------------
Sum: 604
Average: 86.29
Highest: 95
Lowest: 76
------------------------------------------------------------
ADDITIONAL STATISTICS
------------------------------------------------------------
Using built-in functions (for verification):
sum(grades): 604
max(grades): 95
min(grades): 76
len(grades): 7
Average: 86.29
------------------------------------------------------------
ADVANCED: STANDARD DEVIATION
------------------------------------------------------------
Step-by-step calculation:
Mean: 86.29
Sum of squared differences: 259.43
Variance: 37.06
Standard Deviation: 6.09
------------------------------------------------------------
ALTERNATIVE CALCULATION
------------------------------------------------------------
Using **= in loop:
Standard Deviation: 6.09
Matches previous result? ✅ Yes
------------------------------------------------------------
ADVANCED STATISTICS
------------------------------------------------------------
Sorted grades: [76, 78, 85, 88, 90, 92, 95]
Median: 88
Range: 19
Grade Distribution:
A: 2 grade(s)
B: 3 grade(s)
C: 1 grade(s)
D: 1 grade(s)
------------------------------------------------------------
STANDARD DEVIATION STEP-BY-STEP
------------------------------------------------------------
Detailed calculation of standard deviation:
Grades: [85, 92, 78, 90, 88, 76, 95]
Mean: 86.29
Step 1: Calculate squared differences (x - mean)²
Grade | x - mean | (x - mean)²
---------------------------------------------
85 | -1.29 | 1.65
92 | 5.71 | 32.65
78 | -8.29 | 68.65
90 | 3.71 | 13.79
88 | 1.71 | 2.94
76 | -10.29 | 105.79
95 | 8.71 | 75.94
---------------------------------------------
TOTAL | | 259.43
Step 2: Variance = sum_sq / n = 259.43 / 7 = 37.06
Step 3: Standard Deviation = sqrt(Variance) = sqrt(37.06) = 6.09
============================================================
KEY TAKEAWAYS
============================================================
• Use `sum_var += value` to accumulate totals in loops
• Use `value **= 2` to square a value in-place
• Use `value /= n` to divide and assign
• Manual loops can replace built-in functions like sum(), max(), min()
• Augmented assignment makes code more concise
• Standard deviation measures the spread of data around the mean
============================================================
Explanation:
Basic Statistics (Manual Calculations):
+= – sum_grades += grade accumulates the total.avg = sum_grades / len(grades).Advanced Statistics:
σ = sqrt(Σ(x - μ)² / n)**= – diff **= 2 squares the difference in-place.+= – sum_sq_diff += diff_sq accumulates squared differences.math.sqrt() – Calculate the square root.Step-by-Step Standard Deviation:
(value - mean)².Why Standard Deviation Matters:
Write a program that calculates the sum of squares and the sum of cubes of the first 10 positive integers using augmented assignments and loops.
Instructions: Write a program that:
sum_squares = 0 and sum_cubes = 0.i, uses += to add i**2 to sum_squares and i**3 to sum_cubes.**= or ** with 0.5 as exponent.Sample Output:
Sum of squares (1^2 to 10^2): 385
Sum of cubes (1^3 to 10^3): 3025
Square root of sum of squares: 19.621416870348583