Previous | Tutorial index | Next
Write an assignment statement to assign values to variables.
1.1 The Purpose of Assignment: Binding Names to Values
In Python, an assignment statement creates a binding between a name (variable) and an object in memory. Think of it like putting a label on a box:
= operator is the act of sticking the label on the box.Key Insight: Assignment does not copy the value; it simply creates a reference from the variable name to the object. This is why Python is often described as having "variables as references" rather than "variables as containers."
Real-World Analogy:
age = 25, you're taking a sticky note labeled "age" and sticking it onto the number 25 somewhere in your notebook.age = 30, you remove the sticky note from 25 and stick it onto a new number 30. The number 25 still exists in the notebook, but it now has no label.1.2 Basic Syntax: The Simple Assignment Statement
The fundamental form is:
variable_name = expression
5 = 10 is invalid) or a complex expression (e.g., x + y = 10 is invalid).Examples:
# Literal assignment
age = 25
# Variable assignment (copying reference)
my_age = age
# Arithmetic expression
total = price * quantity
# Function call assignment
name_length = len("Python")
# Complex expression
result = (price * quantity) - discount + tax
Multiple Assignment in One Statement: You can assign the same value to multiple variables:
x = y = z = 0
This is called chained assignment. All three variables reference the same object 0. For immutable objects like 0, this is safe.
1.3 Execution Order: The Right Side is Evaluated First
This is a critical concept that causes many bugs for beginners.
The Rule: Python always:
The Famous n = n + 1 Example:
n = 5 # n points to 5
n = n + 1 # Step 1: Calculate n + 1 (5 + 1 = 6)
# Step 2: Assign 6 to n (n now points to 6)
print(n) # 6
Why This Works:
n on the right side is looked up using its current value (5).5 + 1 produces a new object 6.n on the left side is then rebound to point to this new 6 object.5 object is now unreferenced and will be garbage-collected.Memory Diagram of n = n + 1:
Before: n → [5]
Step 1: Read n (5) → Calculate 5+1 = 6 → Create new object [6]
Step 2: Rebind n → [6]
After: n → [6] (old [5] has no references)
Another Example to Solidify Understanding:
a = 10
b = a # b now points to the same object as a (10)
a = a + 5 # Calculate a+5 (15), bind a to new object 15
print(a) # 15
print(b) # 10 (b still points to the old 10 object!)
This demonstrates that b was not affected when a was reassigned because integers are immutable.
1.4 Dynamic Typing: Variables Are Not Fixed to a Type
Python is dynamically typed, meaning:
Example:
x = 10 # x is now an int
print(type(x)) # <class 'int'>
x = "Hello" # x is now a str (completely legal)
print(type(x)) # <class 'str'>
x = [1, 2, 3] # x is now a list
print(type(x)) # <class 'list'>
Why This Matters:
x to be a number and you accidentally assign a string, you'll get runtime errors.Type Checking Safely:
value = input("Enter a number: ") # value is always a string
if value.isdigit(): # Check if it's all digits
number = int(value)
print(f"Doubled: {number * 2}")
else:
print("That's not a valid number.")
1.5 Multiple Assignments (Tuple Unpacking)
Python allows you to assign multiple variables in a single line. This is called tuple unpacking.
Basic Form:
x, y = 3, 4
# Equivalent to: x = 3; y = 4
How It Works Internally:
3, 4 creates a tuple (3, 4).x, y unpacks this tuple, assigning 3 to x and 4 to y.Unpacking Lists and Strings:
# Unpacking a list
a, b, c = [1, 2, 3] # a=1, b=2, c=3
# Unpacking a string (each character)
first, second, third = "ABC" # first='A', second='B', third='C'
# Unpacking with extra values using * (star) operator (Python 3+)
first, *rest = [1, 2, 3, 4] # first=1, rest=[2, 3, 4]
*first, last = [1, 2, 3] # first=[1, 2], last=3
Important: Number of Variables Must Match the Number of Values
x, y = 3, 4, 5 # ValueError: too many values to unpack
x, y = 3 # ValueError: not enough values to unpack
Unpacking Dictionaries (Unpacks Keys):
person = {"name": "Alice", "age": 25}
key1, key2 = person # key1='name', key2='age'
print(key1, key2) # name age
1.6 Swapping Variables: The Pythonic Way
In many programming languages, swapping two variables requires a temporary variable:
# Traditional approach (works in Python too)
temp = a
a = b
b = temp
Python's Elegant Approach:
a, b = b, a
How This Works:
b, a creates a tuple (b, a).a, b unpacks this tuple.a gets the old value of b, and b gets the old value of a.Example:
a = 5
b = 10
print(f"Before: a={a}, b={b}") # Before: a=5, b=10
a, b = b, a
print(f"After: a={a}, b={b}") # After: a=10, b=5
Advanced Swap with More Variables:
x, y, z = 1, 2, 3
x, y, z = z, x, y # Rotates values
print(x, y, z) # 3, 1, 2
1.7 Special Cases: Assignment with Mutable Objects
When you assign a mutable object (like a list or dictionary) to two variables, both variables reference the same object. Changing one affects the other.
Aliasing Example:
list1 = [1, 2, 3]
list2 = list1 # list2 points to the SAME list as list1
list2.append(4) # Modifies the shared list
print(list1) # [1, 2, 3, 4] ← list1 changed too!
print(list2) # [1, 2, 3, 4]
How to Create an Independent Copy:
list2 = list1[:] or list2 = list1.copy()dict2 = dict1.copy()Example of Independent Copy:
list1 = [1, 2, 3]
list2 = list1[:] # Creates a new list object
list2.append(4)
print(list1) # [1, 2, 3] ← unchanged
print(list2) # [1, 2, 3, 4]
1.8 The = Operator vs. == Operator (Crucial Distinction)
New programmers often confuse assignment (=) with equality comparison (==).
| Operator | Purpose | Example | Result |
|---|---|---|---|
= |
Assignment (binds a value to a variable) | x = 10 |
Puts 10 into x |
== |
Equality comparison (asks if two values are equal) | x == 10 |
True or False |
Common Mistake:
if x = 10: # SyntaxError! Use == for comparison
print("x is 10")
Correct Version:
if x == 10: # Correct: checks equality
print("x is 10")
1.9 Assignment in Conditional Contexts (The Walrus Operator – Advanced Preview)
Python 3.8 introduced the walrus operator := (assignment expression), which allows assignment within an expression. This is an advanced topic but worth a brief mention:
# Without walrus operator
data = input("Enter: ")
if len(data) > 0:
print(f"You entered: {data}")
# With walrus operator (combines assignment and condition)
if (data := input("Enter: ")) and len(data) > 0:
print(f"You entered: {data}")
Note: This is optional and not required for this unit. Students can ignore it for now.
# --- Basic Assignment ---
print("--- Basic Assignment ---")
age = 25
name = "Alice"
price = 9.99
quantity = 3
total = price * quantity
print(f"{name} bought {quantity} items for ${total:.2f}")
# --- Execution Order (Right Side First) ---
print("\n--- Execution Order ---")
n = 5
print(f"Before: n = {n}") # 5
n = n + 1
print(f"After: n = {n}") # 6
# Demonstrating that right side is evaluated using current values
a = 10
b = a # b gets the current value of a (10)
a = a + 5
print(f"a = {a}, b = {b}") # a=15, b=10 (b unchanged)
# --- Dynamic Typing ---
print("\n--- Dynamic Typing ---")
x = 10
print(f"x = {x}, type = {type(x)}")
x = "Hello"
print(f"x = {x}, type = {type(x)}")
x = [1, 2, 3]
print(f"x = {x}, type = {type(x)}")
# --- Multiple Assignment ---
print("\n--- Multiple Assignment ---")
x, y = 3, 4
print(f"x = {x}, y = {y}") # 3, 4
# Swapping
print("\n--- Swapping ---")
a, b = 5, 10
print(f"Before: a={a}, b={b}")
a, b = b, a
print(f"After: a={a}, b={b}")
# Chained assignment
x = y = z = 0
print(f"x={x}, y={y}, z={z}")
# --- Mutability and Aliasing ---
print("\n--- Aliasing ---")
list1 = [1, 2, 3]
list2 = list1 # list2 points to the same object
list2.append(4)
print(f"list1: {list1}") # [1, 2, 3, 4]
print(f"list2: {list2}") # [1, 2, 3, 4]
# Creating an independent copy
list3 = list1[:] # Slicing creates a new list
list3.append(5)
print(f"list1 (after copy change): {list1}") # [1, 2, 3, 4] (unchanged)
print(f"list3: {list3}") # [1, 2, 3, 4, 5]
# --- Unpacking Various Types ---
print("\n--- Unpacking ---")
# Tuple unpacking
point = (10, 20)
x, y = point
print(f"Point: x={x}, y={y}")
# List unpacking
colors = ["red", "green", "blue"]
r, g, b = colors
print(f"RGB: {r}, {g}, {b}")
# String unpacking
first, second, third = "ABC"
print(f"Chars: {first}, {second}, {third}")
# Extended unpacking (star operator)
numbers = [1, 2, 3, 4, 5]
first, *middle, last = numbers
print(f"first={first}, middle={middle}, last={last}")
# --- Common Mistake: Using = instead of == ---
print("\n--- Comparison vs Assignment ---")
value = 10
# if value = 10: # SyntaxError!
# print("This won't work")
if value == 10: # Correct
print("Value is 10")
Question 1: What is the output of the following code?
x = 10
y = x
x = 20
print(y)
a) 10
b) 20
c) None
d) Error
Question 2: What is the value of x after x = 5; x = x * 2 + 1?
a) 5
b) 11
c) 12
d) 6
Question 3: What is the output of a, b = b, a if a = 3 and b = 7?
a) a=7, b=3
b) a=3, b=7
c) a=7, b=7
d) a=3, b=3
Question 4: Which of the following is a valid assignment statement?
a) 5 = x
b) x + y = 10
c) x = 10
d) if = 5
Question 5: What is the type of x after x = "123"?
a) int
b) str
c) float
d) bool
Question 6: What happens when you execute x, y = 1, 2, 3?
a) x=1, y=2 (3 ignored)
b) x=1, y=2, x=3
c) ValueError: too many values to unpack
d) SyntaxError
Question 7: Given list1 = [1, 2]; list2 = list1; list2.append(3); print(list1), what is the output?
a) [1, 2]
b) [1, 2, 3]
c) [1, 3]
d) Error
Question 8: What is the difference between x = 10 and x == 10?
a) No difference; both assign 10 to x
b) First assigns 10 to x; second compares x to 10
c) First compares x to 10; second assigns 10 to x
d) Both are invalid
Question 9: Which correctly creates an independent copy of my_list = [1, 2, 3]?
a) copy = my_list
b) copy = my_list[:]
c) copy = my_list.copy()
d) Both b and c
Question 10: What is the output of?
a = 10
b = 20
a, b = b, a + 5
print(a, b)
a) 20 15
b) 20 10
c) 10 20
d) 15 20
cise 1: Assignment Tracing**
Trace the following code manually (without running). Write down the value of each variable after each step.
x = 5
y = 10
z = x + y
x = z + 5
y = x - y
z = y - x
print(x, y, z)
Exercise 2: Swapping Challenge
Write a Python script that takes two numbers from the user and swaps them using the Pythonic method, printing before and after.
Exercise 3: Multiple Assignment Practice
Create a tuple coordinates = (5, 10, 15) and unpack into x, y, z. Also create a list data = [100, 200, 300, 400, 500] and use extended unpacking to get first, middle, last (where middle is a list of middle three).
data = [100, 200, 300, 400, 500] first, *middle, last = data print(first, middle, last) # 100, [200, 300, 400], 500
</details>
**Exercise 4: Dynamic Typing Experiment**
Write a program that:
1. Creates a variable `var` and assigns it the value `10`.
2. Prints `var` and its type.
3. Reassigns `var` to `"Python"`.
4. Prints `var` and its type.
5. Reassigns `var` to `[1, 2, 3]`.
6. Prints `var` and its type.
7. Reassigns `var` to `True`.
8. Prints `var` and its type.
9. Explain in comments why this is possible in Python.
**Exercise 5: Aliasing vs. Copying**
Write a script that demonstrates:
1. Creating a list `original = [10, 20, 30]`.
2. Creating a reference `alias = original`.
3. Creating an independent copy `copy = original[:]`.
4. Modifying the first element of `alias` to 99.
5. Printing `original`, `alias`, and `copy` to show:
- `original` and `alias` are the same.
- `copy` is independent.
6. Now modify the first element of `copy` to 55.
7. Print all three lists again to confirm `original` hasn't changed.
## 5. Homework Questions (Deep Thinking)
Here are the rewritten exercises with comprehensive sample answers added.
**Exercise 4: Dynamic Typing Experiment**
Write a program that:
1. Creates a variable `var` and assigns it the value `10`.
2. Prints `var` and its type.
3. Reassigns `var` to `"Python"`.
4. Prints `var` and its type.
5. Reassigns `var` to `[1, 2, 3]`.
6. Prints `var` and its type.
7. Reassigns `var` to `True`.
8. Prints `var` and its type.
9. Explain in comments why this is possible in Python.
<details><summary>Sample Answer</summary>
```python
"""
DYNAMIC TYPING EXPERIMENT
Demonstrating Python's dynamic typing feature
"""
print("=" * 60)
print("DYNAMIC TYPING EXPERIMENT")
print("=" * 60)
# Step 1 & 2: Assign integer and print
var = 10
print(f"Step 1 & 2 - var = {var}, type = {type(var)}")
# Step 3 & 4: Reassign to string
var = "Python"
print(f"Step 3 & 4 - var = '{var}', type = {type(var)}")
# Step 5 & 6: Reassign to list
var = [1, 2, 3]
print(f"Step 5 & 6 - var = {var}, type = {type(var)}")
# Step 7 & 8: Reassign to boolean
var = True
print(f"Step 7 & 8 - var = {var}, type = {type(var)}")
print("\n" + "=" * 60)
print("EXPLANATION (in comments)")
print("=" * 60)
"""
EXPLANATION:
This code works because Python is a dynamically typed language.
The key concepts are:
1. Variables are just names (references) to objects in memory.
They do not have a fixed type themselves.
2. The type of a variable is determined by the object it currently
references. When we reassign a variable, we are changing what
object it points to.
3. Python does not require variable type declarations. Unlike
statically typed languages (like Java or C++), where you must
declare int x = 10; and cannot later assign x = "Hello",
Python allows this because it checks types at runtime.
4. Under the hood, when we do:
var = 10 → var points to an integer object
var = "Python" → var now points to a string object
The old integer object is garbage-collected if no other
references exist.
5. This flexibility makes Python easier to use but requires
careful programming to avoid type-related runtime errors.
"""
print("\nAdditional demonstration:")
# Showing that we can even change type within an expression
value = 5
print(f"value = {value}, type: {type(value)}")
value = value + 3.14 # int + float → float
print(f"value = {value}, type: {type(value)}")
# Further examples of dynamic typing
def print_value(x):
"""A function that works with any type."""
print(f"Received: {x}, type: {type(x)}")
print("\nFunction with dynamic parameter:")
print_value(100)
print_value("Dynamic!")
print_value([1, 2, 3])
print_value(True)
print("\n" + "=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • Python variables are dynamically typed")
print(" • Variables can be reassigned to any type at any time")
print(" • The type is determined by the value, not the variable")
print(" • This is possible because Python is an interpreted language")
print(" • Type checking happens at runtime (not compile time)")
print(" • This flexibility comes with responsibility to avoid type errors")
print("=" * 60)
Sample Output:
============================================================
DYNAMIC TYPING EXPERIMENT
============================================================
Step 1 & 2 - var = 10, type = <class 'int'>
Step 3 & 4 - var = 'Python', type = <class 'str'>
Step 5 & 6 - var = [1, 2, 3], type = <class 'list'>
Step 7 & 8 - var = True, type = <class 'bool'>
============================================================
EXPLANATION (in comments)
============================================================
Additional demonstration:
value = 5, type: <class 'int'>
value = 8.14, type: <class 'float'>
Function with dynamic parameter:
Received: 100, type: <class 'int'>
Received: Dynamic!, type: <class 'str'>
Received: [1, 2, 3], type: <class 'list'>
Received: True, type: <class 'bool'>
============================================================
KEY TAKEAWAYS
============================================================
• Python variables are dynamically typed
• Variables can be reassigned to any type at any time
• The type is determined by the value, not the variable
• This is possible because Python is an interpreted language
• Type checking happens at runtime (not compile time)
• This flexibility comes with responsibility to avoid type errors
============================================================
Explanation of Dynamic Typing:
No Type Declaration: In Python, you don't declare int x; you just write x = 10.
Type is Runtime Property: The type of x is determined by the value it holds at any given moment.
Reassignment Changes Type: When you assign a new value of a different type, the variable's type changes.
Behind the Scenes: Each object in Python has a type tag. Variables are just references that can point to any object.
Advantages: More flexible, less boilerplate, easier prototyping.
Disadvantages: Can lead to type-related bugs if not careful (e.g., treating a string as a number).
Exercise 5: Aliasing vs. Copying
Write a script that demonstrates:
original = [10, 20, 30].alias = original.copy = original[:].alias to 99.original, alias, and copy to show:
original and alias are the same.copy is independent.copy to 55.original hasn't changed."""
ALIASING VS. COPYING
Demonstrating the difference between reference assignment and creating a copy
"""
print("=" * 60)
print("ALIASING VS. COPYING")
print("=" * 60)
# --- Step 1: Create the original list ---
original = [10, 20, 30]
print(f"Step 1 - original: {original}")
print(f" ID of original: {id(original)}")
# --- Step 2: Create an alias (reference) ---
alias = original
print(f"\nStep 2 - alias = original")
print(f" alias: {alias}")
print(f" ID of alias: {id(alias)}")
print(f" Are they the same object? {original is alias}") # True
# --- Step 3: Create an independent copy using slicing ---
copy = original[:]
print(f"\nStep 3 - copy = original[:]")
print(f" copy: {copy}")
print(f" ID of copy: {id(copy)}")
print(f" Are they the same object? {original is copy}") # False
print("\n" + "-" * 60)
print("BEFORE MODIFICATION")
print("-" * 60)
print(f"original: {original}")
print(f"alias: {alias}")
print(f"copy: {copy}")
# --- Step 4: Modify the alias (affects original) ---
alias[0] = 99
print("\n" + "-" * 60)
print("STEP 4: AFTER MODIFYING alias[0] = 99")
print("-" * 60)
print(f"original: {original}") # Changed!
print(f"alias: {alias}") # Changed!
print(f"copy: {copy}") # Unchanged (independent)
# --- Step 5: Show that original and alias are the same ---
print("\n" + "-" * 60)
print("STEP 5: VERIFICATION")
print("-" * 60)
print(f"'original is alias' → {original is alias}") # True
print(f"'original is copy' → {original is copy}") # False
# --- Step 6: Modify the copy (does NOT affect original) ---
copy[0] = 55
print("\n" + "-" * 60)
print("STEP 6: AFTER MODIFYING copy[0] = 55")
print("-" * 60)
print(f"original: {original}") # Still [99, 20, 30]
print(f"alias: {alias}") # Still [99, 20, 30]
print(f"copy: {copy}") # Changed to [55, 20, 30]
# --- Step 7: Confirm original hasn't changed ---
print("\n" + "-" * 60)
print("STEP 7: FINAL CHECK - original unchanged?")
print("-" * 60)
print(f"original: {original}")
print(f"copy: {copy}")
print(f"Are original and copy equal? {original == copy}") # False
print(f"Did original change? {'✅ No' if original == [99, 20, 30] else '❌ Yes'}")
print("\n" + "=" * 60)
print("MEMORY DIAGRAM (CONCEPTUAL)")
print("=" * 60)
# Visual representation of memory
print("""
After Step 1-3:
original ──→ [10, 20, 30] (Object A at address 1000)
alias ──→ [10, 20, 30] (Same object A - alias points to same address)
copy ──→ [10, 20, 30] (Object B at address 2000 - independent copy)
After Step 4 (alias[0] = 99):
original ──→ [99, 20, 30] (Object A modified in-place)
alias ──→ [99, 20, 30] (Still points to Object A - sees the change)
copy ──→ [10, 20, 30] (Object B unchanged - independent)
After Step 6 (copy[0] = 55):
original ──→ [99, 20, 30] (Object A remains as modified)
alias ──→ [99, 20, 30] (Object A remains as modified)
copy ──→ [55, 20, 30] (Object B modified in-place - independent)
""")
print("=" * 60)
print("KEY TAKEAWAYS")
print("=" * 60)
print(" • 'alias = original' creates an alias (both point to same object)")
print(" • 'copy = original[:]' creates an independent copy (new object)")
print(" • Modifying the alias modifies the original (shared object)")
print(" • Modifying the copy does NOT affect the original")
print(" • Use 'is' to check object identity (same object) vs '==' (same value)")
print(" • Always copy mutable objects when you need independent data")
print("=" * 60)
print("\n" + "=" * 60)
print("ADDITIONAL COPY METHODS")
print("=" * 60)
# More ways to create independent copies
print("\nCreating independent copies of a list:")
original = [10, 20, 30]
# Method 1: Slicing (most common)
copy1 = original[:]
print(f" Method 1 - original[:]: {copy1} (id: {id(copy1)})")
# Method 2: list() constructor
copy2 = list(original)
print(f" Method 2 - list(original): {copy2} (id: {id(copy2)})")
# Method 3: .copy() method (Python 3.3+)
copy3 = original.copy()
print(f" Method 3 - original.copy(): {copy3} (id: {id(copy3)})")
# Method 4: copy module (for deep copying, beyond scope)
# import copy
# copy4 = copy.deepcopy(original) # For nested structures
print("\nAll copies are independent:")
print(f" original is copy1? {original is copy1}") # False
print(f" original is copy2? {original is copy2}") # False
print(f" original is copy3? {original is copy3}") # False
print(" All have different object identities!")
print("\n" + "=" * 60)
print("WHEN TO USE ALIAS VS. COPY")
print("=" * 60)
print("""
Use ALIAS when:
• You want multiple variables to reference the same data
• You want to pass a mutable object to a function that should modify it
• You are working with large data and want to avoid copying overhead
Use COPY when:
• You need to preserve the original data
• You want to modify data without affecting other references
• You are passing data to a function that should not modify the original
""")
print("=" * 60)
Sample Output:
============================================================
ALIASING VS. COPYING
============================================================
Step 1 - original: [10, 20, 30]
ID of original: 140734567890123
Step 2 - alias = original
alias: [10, 20, 30]
ID of alias: 140734567890123
Are they the same object? True
Step 3 - copy = original[:]
copy: [10, 20, 30]
ID of copy: 140734567890456
Are they the same object? False
------------------------------------------------------------
BEFORE MODIFICATION
------------------------------------------------------------
original: [10, 20, 30]
alias: [10, 20, 30]
copy: [10, 20, 30]
------------------------------------------------------------
STEP 4: AFTER MODIFYING alias[0] = 99
------------------------------------------------------------
original: [99, 20, 30]
alias: [99, 20, 30]
copy: [10, 20, 30]
------------------------------------------------------------
STEP 5: VERIFICATION
------------------------------------------------------------
'original is alias' → True
'original is copy' → False
------------------------------------------------------------
STEP 6: AFTER MODIFYING copy[0] = 55
------------------------------------------------------------
original: [99, 20, 30]
alias: [99, 20, 30]
copy: [55, 20, 30]
------------------------------------------------------------
STEP 7: FINAL CHECK - original unchanged?
------------------------------------------------------------
original: [99, 20, 30]
copy: [55, 20, 30]
Are original and copy equal? False
Did original change? ✅ No
============================================================
MEMORY DIAGRAM (CONCEPTUAL)
============================================================
After Step 1-3:
original ──→ [10, 20, 30] (Object A at address 1000)
alias ──→ [10, 20, 30] (Same object A - alias points to same address)
copy ──→ [10, 20, 30] (Object B at address 2000 - independent copy)
After Step 4 (alias[0] = 99):
original ──→ [99, 20, 30] (Object A modified in-place)
alias ──→ [99, 20, 30] (Still points to Object A - sees the change)
copy ──→ [10, 20, 30] (Object B unchanged - independent)
After Step 6 (copy[0] = 55):
original ──→ [99, 20, 30] (Object A remains as modified)
alias ──→ [99, 20, 30] (Object A remains as modified)
copy ──→ [55, 20, 30] (Object B modified in-place - independent)
============================================================
KEY TAKEAWAYS
============================================================
• 'alias = original' creates an alias (both point to same object)
• 'copy = original[:]' creates an independent copy (new object)
• Modifying the alias modifies the original (shared object)
• Modifying the copy does NOT affect the original
• Use 'is' to check object identity (same object) vs '==' (same value)
• Always copy mutable objects when you need independent data
============================================================
============================================================
ADDITIONAL COPY METHODS
============================================================
Creating independent copies of a list:
Method 1 - original[:]: [10, 20, 30] (id: 140734567890789)
Method 2 - list(original): [10, 20, 30] (id: 140734567890123)
Method 3 - original.copy(): [10, 20, 30] (id: 140734567890456)
All copies are independent:
original is copy1? False
original is copy2? False
original is copy3? False
All have different object identities!
============================================================
WHEN TO USE ALIAS VS. COPY
============================================================
Use ALIAS when:
• You want multiple variables to reference the same data
• You want to pass a mutable object to a function that should modify it
• You are working with large data and want to avoid copying overhead
Use COPY when:
• You need to preserve the original data
• You want to modify data without affecting other references
• You are passing data to a function that should not modify the original
============================================================
Explanation:
Key Concepts:
Alias (alias = original):
Independent Copy (copy = original[:] or list(original) or original.copy()):
Object Identity (is):
original is alias → True (same object)original is copy → False (different objects)Value Equality (==):
original == copy → True (same contents at creation)original == copy may become False.Memory Diagram:
Why This Matters:
Avoiding Unintended Side Effects: If you have multiple variables referencing the same list, changing one can break other parts of your code.
Function Arguments: Passing a list to a function can result in the function modifying the original list unless you pass a copy.
Data Integrity: When you need to keep an original version, always make a copy before modifying.
Performance: Aliasing is more memory-efficient because it doesn't create new objects. Use it when you intentionally want to share data.
Common Bugs: Many beginners are surprised when modifying a "copy" that was actually an alias. This exercise helps avoid that trap.
Write a program that takes a list of values and swaps every pair in the list (e.g., [1, 2, 3, 4] → [2, 1, 4, 3]).
Instructions (Advanced Homework Bonus): Write a program that:
numbers = [10, 20, 30, 40, 50, 60].Sample Output:
Before: [10, 20, 30, 40, 50, 60]
After: [20, 10, 40, 30, 60, 50]