Python Specific
Unpacking
When processing data from APIs, files, or databases, you often receive structured data that needs to be split into individual variables. Unpacking lets you extract values from sequences and mappings in a single, readable operation instead of using multiple index accesses.
Unpacking allows extracting values from sequences (lists, tuples) and mappings (dicts) into separate variables in a single operation.
Basic Unpacking
"""Basic unpacking examples"""
# Tuple unpacking
print("Tuple unpacking:")
point = (10, 20)
x, y = point
print(f"point = {point}")
print(f"x = {x}, y = {y}")
# Swap variables
a, b = 5, 10
print(f"\nBefore swap: a={a}, b={b}")
a, b = b, a
print(f"After swap: a={a}, b={b}")
# List unpacking
print("\nList unpacking:")
coordinates = [100, 200, 300]
x, y, z = coordinates
print(f"coordinates = {coordinates}")
print(f"x={x}, y={y}, z={z}")
# String unpacking
print("\nString unpacking:")
name = "Alice"
first, second, third, fourth, fifth = name
print(f"name = '{name}'")
print(f"Letters: {first}, {second}, {third}, {fourth}, {fifth}")
# Multiple assignment
print("\nMultiple assignment:")
# Single line assignment
a, b, c = 1, 2, 3
print(f"a={a}, b={b}, c={c}")
# From list
values = [10, 20, 30]
x, y, z = values
print(f"x={x}, y={y}, z={z}")
# Function returns
print("\nFunction returns:")
def get_user():
return "Alice", 30, "alice@example.com"
name, age, email = get_user()
print(f"User: {name}, {age}, {email}")
def min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = min_max([5, 2, 8, 1, 9])
print(f"Min: {minimum}, Max: {maximum}")
# Enumerate unpacking
print("\nEnumerate unpacking:")
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
print(f" {index}: {fruit}")
# Dict items unpacking
print("\nDict items unpacking:")
user = {"name": "Bob", "age": 25, "city": "NYC"}
for key, value in user.items():
print(f" {key}: {value}")
# Zip unpacking
print("\nZip unpacking:")
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f" {name}: {score}")
# Nested tuples
print("\nNested tuples:")
data = ("Alice", (30, "alice@example.com"))
name, (age, email) = data
print(f"name={name}, age={age}, email={email}")
# Error handling
print("\nError handling:")
try:
a, b = [1, 2, 3] # Too many values
except ValueError as e:
print(f"Error: {e}")
try:
a, b, c = [1, 2] # Too few values
except ValueError as e:
print(f"Error: {e}")
# Underscore for ignored values
print("\nUnderscore for ignored values:")
# Ignore some values
first, _, third = [1, 2, 3]
print(f"first={first}, third={third} (ignored middle)")
name, _, _, city = ["Alice", 30, "alice@example.com", "NYC"]
print(f"name={name}, city={city} (ignored age and email)")
# Practical example
print("\nPractical example:")
def parse_coordinate(coord_str):
"""Parse 'x,y' string into tuple"""
return tuple(map(int, coord_str.split(',')))
coord_str = "100,200"
x, y = parse_coordinate(coord_str)
print(f"Parsed '{coord_str}': x={x}, y={y}")
# Process CSV line
csv_line = "Alice,30,Engineer"
name, age, job = csv_line.split(',')
print(f"CSV: name={name}, age={age}, job={job}")
"""Basic unpacking examples"""
# Tuple unpacking
print("Tuple unpacking:")
point = (3, 4)
x, y = point
print(f"point = {point}")
print(f"x = {x}, y = {y}")
# Swap variables
a, b = 5, 10
print(f"\nBefore swap: a={a}, b={b}")
a, b = b, a
print(f"After swap: a={a}, b={b}")
# List unpacking
print("\nList unpacking:")
coordinates = [100, 200, 300]
x, y, z = coordinates
print(f"coordinates = {coordinates}")
print(f"x={x}, y={y}, z={z}")
# String unpacking
print("\nString unpacking:")
name = "Alice"
first, second, third, fourth, fifth = name
print(f"name = '{name}'")
print(f"Letters: {first}, {second}, {third}, {fourth}, {fifth}")
# Multiple assignment
print("\nMultiple assignment:")
# Single line assignment
a, b, c = 1, 2, 3
print(f"a={a}, b={b}, c={c}")
# From list
values = [10, 20, 30]
x, y, z = values
print(f"x={x}, y={y}, z={z}")
# Function returns
print("\nFunction returns:")
def get_user():
return "Alice", 30, "alice@example.com"
name, age, email = get_user()
print(f"User: {name}, {age}, {email}")
def min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = min_max([5, 2, 8, 1, 9])
print(f"Min: {minimum}, Max: {maximum}")
# Enumerate unpacking
print("\nEnumerate unpacking:")
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
print(f" {index}: {fruit}")
# Dict items unpacking
print("\nDict items unpacking:")
user = {"name": "Bob", "age": 25, "city": "NYC"}
for key, value in user.items():
print(f" {key}: {value}")
# Zip unpacking
print("\nZip unpacking:")
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f" {name}: {score}")
# Nested tuples
print("\nNested tuples:")
data = ("Alice", (30, "alice@example.com"))
name, (age, email) = data
print(f"name={name}, age={age}, email={email}")
# Error handling
print("\nError handling:")
try:
a, b = [1, 2, 3] # Too many values
except ValueError as e:
print(f"Error: {e}")
try:
a, b, c = [1, 2] # Too few values
except ValueError as e:
print(f"Error: {e}")
# Underscore for ignored values
print("\nUnderscore for ignored values:")
# Ignore some values
first, _, third = [1, 2, 3]
print(f"first={first}, third={third} (ignored middle)")
name, _, _, city = ["Alice", 30, "alice@example.com", "NYC"]
print(f"name={name}, city={city} (ignored age and email)")
# Practical example
print("\nPractical example:")
def parse_coordinate(coord_str):
"""Parse 'x,y' string into tuple"""
return tuple(map(int, coord_str.split(',')))
coord_str = "100,200"
x, y = parse_coordinate(coord_str)
print(f"Parsed '{coord_str}': x={x}, y={y}")
# Process CSV line
csv_line = "Alice,30,Engineer"
name, age, job = csv_line.split(',')
print(f"CSV: name={name}, age={age}, job={job}")
"""Basic unpacking examples"""
# Tuple unpacking
print("Tuple unpacking:")
point = (100, 200)
x, y = point
print(f"point = {point}")
print(f"x = {x}, y = {y}")
# Swap variables
a, b = 5, 10
print(f"\nBefore swap: a={a}, b={b}")
a, b = b, a
print(f"After swap: a={a}, b={b}")
# List unpacking
print("\nList unpacking:")
coordinates = [100, 200, 300]
x, y, z = coordinates
print(f"coordinates = {coordinates}")
print(f"x={x}, y={y}, z={z}")
# String unpacking
print("\nString unpacking:")
name = "Alice"
first, second, third, fourth, fifth = name
print(f"name = '{name}'")
print(f"Letters: {first}, {second}, {third}, {fourth}, {fifth}")
# Multiple assignment
print("\nMultiple assignment:")
# Single line assignment
a, b, c = 1, 2, 3
print(f"a={a}, b={b}, c={c}")
# From list
values = [10, 20, 30]
x, y, z = values
print(f"x={x}, y={y}, z={z}")
# Function returns
print("\nFunction returns:")
def get_user():
return "Alice", 30, "alice@example.com"
name, age, email = get_user()
print(f"User: {name}, {age}, {email}")
def min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = min_max([5, 2, 8, 1, 9])
print(f"Min: {minimum}, Max: {maximum}")
# Enumerate unpacking
print("\nEnumerate unpacking:")
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
print(f" {index}: {fruit}")
# Dict items unpacking
print("\nDict items unpacking:")
user = {"name": "Bob", "age": 25, "city": "NYC"}
for key, value in user.items():
print(f" {key}: {value}")
# Zip unpacking
print("\nZip unpacking:")
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f" {name}: {score}")
# Nested tuples
print("\nNested tuples:")
data = ("Alice", (30, "alice@example.com"))
name, (age, email) = data
print(f"name={name}, age={age}, email={email}")
# Error handling
print("\nError handling:")
try:
a, b = [1, 2, 3] # Too many values
except ValueError as e:
print(f"Error: {e}")
try:
a, b, c = [1, 2] # Too few values
except ValueError as e:
print(f"Error: {e}")
# Underscore for ignored values
print("\nUnderscore for ignored values:")
# Ignore some values
first, _, third = [1, 2, 3]
print(f"first={first}, third={third} (ignored middle)")
name, _, _, city = ["Alice", 30, "alice@example.com", "NYC"]
print(f"name={name}, city={city} (ignored age and email)")
# Practical example
print("\nPractical example:")
def parse_coordinate(coord_str):
"""Parse 'x,y' string into tuple"""
return tuple(map(int, coord_str.split(',')))
coord_str = "100,200"
x, y = parse_coordinate(coord_str)
print(f"Parsed '{coord_str}': x={x}, y={y}")
# Process CSV line
csv_line = "Alice,30,Engineer"
name, age, job = csv_line.split(',')
print(f"CSV: name={name}, age={age}, job={job}")
point ← (10, 20), x ← 10, y ← 20, a ← 5, b ← 10, coordinates ← [100, 200, 300]
1"""Basic unpacking examples"""23# Tuple unpacking4print("Tuple unpacking:")56point→ (10, 20) = (10, 20) #@point=(3, 4), (100, 200)7x→ 10, y→ 20 = point(10, 20)8print(f"point = {point(10, 20)}")9print(f"x = {x10}, y = {y20}")1011# Swap variables12a→ 5, b→ 10 = 5, 1013print(f"\nBefore swap: a={a5}, b={b10}")14a→ 10, b→ 5 = b, a15print(f"After swap: a={a10}, b={b5}")1617# List unpacking18print("\nList unpacking:")1920coordinates→ [100, 200, 300] = [100, 200, 300]21x→ 100, y→ 200, z→ 300 = coordinates[100, 200, 300]22print(f"coordinates = {coordinates[100, 200, 300]}")23print(f"x={x100}, y={y200}, z={z300}")2425# String unpacking26print("\nString unpacking:")2728name→ Alice = "Alice"29first→ A, second→ l, third→ i, fourth→ c, fifth→ e = nameAlice30print(f"name = '{nameAlice}'")31print(f"Letters: {firstA}, {secondl}, {thirdi}, {fourthc}, {fifthe}")3233# Multiple assignment34print("\nMultiple assignment:")3536# Single line assignment37a→ 1, b→ 2, c→ 3 = 1, 2, 338print(f"a={a1}, b={b2}, c={c3}")3940# From list41values→ [10, 20, 30] = [10, 20, 30]42x→ 10, y→ 20, z→ 30 = values[10, 20, 30]43print(f"x={x10}, y={y20}, z={z30}")4445# Function returns46print("\nFunction returns:")4748def get_user():49 return "Alice", 30, "alice@example.com"5051name, age, email = get_user()52print(f"User: {name}, {age}, {email}")outputTuple unpacking: point = (10, 20) x = 10, y = 20 Before swap: a=5, b=10 After swap: a=10, b=5 List unpacking: coordinates = [100, 200, 300] x=100, y=200, z=300 String unpacking: name = 'Alice' Letters: A, l, i, c, e Multiple assignment: a=1, b=2, c=3 x=10, y=20, z=30 Function returns:name ← Alice, age ← 30, email ← alice@example.com
51name→ Alice, age→ 30, email→ alice@example.com = get_user()52print(f"User: {nameAlice}, {age30}, {emailalice@example.com}")5354def min_max(numbers):55 return min(numbers), max(numbers)5657minimum, maximum = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum}, Max: {maximum}")outputUser: Alice, 30, alice@example.comdef min_max(numbers):
54def min_max(numbers[5, 2, 8, 1, 9]):55 return min(numbers[5, 2, 8, 1, 9]), max(numbers)minimum ← 1, maximum ← 9, fruits ← ['apple', 'banana', 'cherry']
57minimum→ 1, maximum→ 9 = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum1}, Max: {maximum9}")5960# Enumerate unpacking61print("\nEnumerate unpacking:")6263fruits→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]outputMin: 1, Max: 9 Enumerate unpacking:for index, fruit in enumerate(fruits):
pass 1 of 365for index0, fruitapple in enumerate(fruits['apple', 'banana', 'cherry']):66 print(f" {index0}: {fruitapple}")output 0: appleAll 3 passes — pass 1 is the card above pass indexfruit1 0 apple 2 1 banana 3 2 cherry user ← {'name': 'Bob', 'age': 25, 'city': 'NYC'}
68# Dict items unpacking69print("\nDict items unpacking:")7071user→ {'name': 'Bob', 'age': 25, 'city': 'NYC'} = {"name": "Bob", "age": 25, "city": "NYC"}output Dict items unpacking:for key, value in user.items():
pass 1 of 373for keyname, valueBob in user{'name': 'Bob', 'age': 25, 'city': 'NYC'}.items():74 print(f" {keyname}: {valueBob}")output name: BobAll 3 passes — pass 1 is the card above pass keyvalue1 name Bob 2 age 25 3 city NYC names ← ['Alice', 'Bob', 'Charlie'], scores ← [85, 92, 78]
76# Zip unpacking77print("\nZip unpacking:")7879names→ ['Alice', 'Bob', 'Charlie'] = ["Alice", "Bob", "Charlie"]80scores→ [85, 92, 78] = [85, 92, 78]output Zip unpacking:for name, score in zip(names, scores):
pass 1 of 382for nameAlice, score85 in zip(names['Alice', 'Bob', 'Charlie'], scores[85, 92, 78]):83 print(f" {nameAlice}: {score85}")output Alice: 85All 3 passes — pass 1 is the card above pass namescore1 Alice 85 2 Bob 92 3 Charlie 78 data ← ('Alice', (30, 'alice@example.com')), name ← Alice, age ← 30
85# Nested tuples86print("\nNested tuples:")8788data→ ('Alice', (30, 'alice@example.com')) = ("Alice", (30, "alice@example.com"))89name→ Alice, (age→ 30, email→ alice@example.com) = data('Alice', (30, 'alice@example.com'))90print(f"name={nameAlice}, age={age30}, email={emailalice@example.com}")9192# Error handling93print("\nError handling:")output Nested tuples: name=Alice, age=30, email=alice@example.com Error handling:except ValueError as e:
96 a, b = [1, 2, 3] # Too many values97except ValueError as e:98 print(f"Error: {etoo many values to unpack (expected 2)}")outputError: too many values to unpack (expected 2)except ValueError as e:
101 a, b, c = [1, 2] # Too few values102except ValueError as e:103 print(f"Error: {enot enough values to unpack (expected 3, got 2)}")outputError: not enough values to unpack (expected 3, got 2)first ← 1, _ ← 2, third ← 3, name ← Alice, city ← NYC, coord_str ← 100,200
105# Underscore for ignored values106print("\nUnderscore for ignored values:")107108# Ignore some values109first→ 1, _→ 2, third→ 3 = [1, 2, 3]110print(f"first={first1}, third={third3} (ignored middle)")111112name→ Alice, _→ alice@example.com, _, city→ NYC = ["Alice", 30, "alice@example.com", "NYC"]113print(f"name={nameAlice}, city={cityNYC} (ignored age and email)")114115# Practical example116print("\nPractical example:")117118def parse_coordinate(coord_str):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str.split(',')))121122coord_str→ 100,200 = "100,200"123x, y = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str}': x={x}, y={y}")output Underscore for ignored values: first=1, third=3 (ignored middle) name=Alice, city=NYC (ignored age and email) Practical example:def parse_coordinate(coord_str):
118def parse_coordinate(coord_str100,200):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str100,200.split(',')))x ← 100, y ← 200, csv_line ← Alice,30,Engineer, name ← Alice, age ← 30
122coord_str = "100,200"123x→ 100, y→ 200 = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str100,200}': x={x100}, y={y200}")125126# Process CSV line127csv_line→ Alice,30,Engineer = "Alice,30,Engineer"128name→ Alice, age→ 30, job→ Engineer = csv_lineAlice,30,Engineer.split(',')129print(f"CSV: name={nameAlice}, age={age30}, job={jobEngineer}")outputParsed '100,200': x=100, y=200 CSV: name=Alice, age=30, job=Engineer
point ← (3, 4), x ← 3, y ← 4, a ← 5, b ← 10, coordinates ← [100, 200, 300]
1"""Basic unpacking examples"""23# Tuple unpacking4print("Tuple unpacking:")56point→ (3, 4) = (3, 4)7x→ 3, y→ 4 = point(3, 4)8print(f"point = {point(3, 4)}")9print(f"x = {x3}, y = {y4}")1011# Swap variables12a→ 5, b→ 10 = 5, 1013print(f"\nBefore swap: a={a5}, b={b10}")14a→ 10, b→ 5 = b, a15print(f"After swap: a={a10}, b={b5}")1617# List unpacking18print("\nList unpacking:")1920coordinates→ [100, 200, 300] = [100, 200, 300]21x→ 100, y→ 200, z→ 300 = coordinates[100, 200, 300]22print(f"coordinates = {coordinates[100, 200, 300]}")23print(f"x={x100}, y={y200}, z={z300}")2425# String unpacking26print("\nString unpacking:")2728name→ Alice = "Alice"29first→ A, second→ l, third→ i, fourth→ c, fifth→ e = nameAlice30print(f"name = '{nameAlice}'")31print(f"Letters: {firstA}, {secondl}, {thirdi}, {fourthc}, {fifthe}")3233# Multiple assignment34print("\nMultiple assignment:")3536# Single line assignment37a→ 1, b→ 2, c→ 3 = 1, 2, 338print(f"a={a1}, b={b2}, c={c3}")3940# From list41values→ [10, 20, 30] = [10, 20, 30]42x→ 10, y→ 20, z→ 30 = values[10, 20, 30]43print(f"x={x10}, y={y20}, z={z30}")4445# Function returns46print("\nFunction returns:")4748def get_user():49 return "Alice", 30, "alice@example.com"5051name, age, email = get_user()52print(f"User: {name}, {age}, {email}")outputTuple unpacking: point = (3, 4) x = 3, y = 4 Before swap: a=5, b=10 After swap: a=10, b=5 List unpacking: coordinates = [100, 200, 300] x=100, y=200, z=300 String unpacking: name = 'Alice' Letters: A, l, i, c, e Multiple assignment: a=1, b=2, c=3 x=10, y=20, z=30 Function returns:name ← Alice, age ← 30, email ← alice@example.com
51name→ Alice, age→ 30, email→ alice@example.com = get_user()52print(f"User: {nameAlice}, {age30}, {emailalice@example.com}")5354def min_max(numbers):55 return min(numbers), max(numbers)5657minimum, maximum = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum}, Max: {maximum}")outputUser: Alice, 30, alice@example.comdef min_max(numbers):
54def min_max(numbers[5, 2, 8, 1, 9]):55 return min(numbers[5, 2, 8, 1, 9]), max(numbers)minimum ← 1, maximum ← 9, fruits ← ['apple', 'banana', 'cherry']
57minimum→ 1, maximum→ 9 = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum1}, Max: {maximum9}")5960# Enumerate unpacking61print("\nEnumerate unpacking:")6263fruits→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]outputMin: 1, Max: 9 Enumerate unpacking:for index, fruit in enumerate(fruits):
pass 1 of 365for index0, fruitapple in enumerate(fruits['apple', 'banana', 'cherry']):66 print(f" {index0}: {fruitapple}")output 0: appleAll 3 passes — pass 1 is the card above pass indexfruit1 0 apple 2 1 banana 3 2 cherry user ← {'name': 'Bob', 'age': 25, 'city': 'NYC'}
68# Dict items unpacking69print("\nDict items unpacking:")7071user→ {'name': 'Bob', 'age': 25, 'city': 'NYC'} = {"name": "Bob", "age": 25, "city": "NYC"}output Dict items unpacking:for key, value in user.items():
pass 1 of 373for keyname, valueBob in user{'name': 'Bob', 'age': 25, 'city': 'NYC'}.items():74 print(f" {keyname}: {valueBob}")output name: BobAll 3 passes — pass 1 is the card above pass keyvalue1 name Bob 2 age 25 3 city NYC names ← ['Alice', 'Bob', 'Charlie'], scores ← [85, 92, 78]
76# Zip unpacking77print("\nZip unpacking:")7879names→ ['Alice', 'Bob', 'Charlie'] = ["Alice", "Bob", "Charlie"]80scores→ [85, 92, 78] = [85, 92, 78]output Zip unpacking:for name, score in zip(names, scores):
pass 1 of 382for nameAlice, score85 in zip(names['Alice', 'Bob', 'Charlie'], scores[85, 92, 78]):83 print(f" {nameAlice}: {score85}")output Alice: 85All 3 passes — pass 1 is the card above pass namescore1 Alice 85 2 Bob 92 3 Charlie 78 data ← ('Alice', (30, 'alice@example.com')), name ← Alice, age ← 30
85# Nested tuples86print("\nNested tuples:")8788data→ ('Alice', (30, 'alice@example.com')) = ("Alice", (30, "alice@example.com"))89name→ Alice, (age→ 30, email→ alice@example.com) = data('Alice', (30, 'alice@example.com'))90print(f"name={nameAlice}, age={age30}, email={emailalice@example.com}")9192# Error handling93print("\nError handling:")output Nested tuples: name=Alice, age=30, email=alice@example.com Error handling:except ValueError as e:
96 a, b = [1, 2, 3] # Too many values97except ValueError as e:98 print(f"Error: {etoo many values to unpack (expected 2)}")outputError: too many values to unpack (expected 2)except ValueError as e:
101 a, b, c = [1, 2] # Too few values102except ValueError as e:103 print(f"Error: {enot enough values to unpack (expected 3, got 2)}")outputError: not enough values to unpack (expected 3, got 2)first ← 1, _ ← 2, third ← 3, name ← Alice, city ← NYC, coord_str ← 100,200
105# Underscore for ignored values106print("\nUnderscore for ignored values:")107108# Ignore some values109first→ 1, _→ 2, third→ 3 = [1, 2, 3]110print(f"first={first1}, third={third3} (ignored middle)")111112name→ Alice, _→ alice@example.com, _, city→ NYC = ["Alice", 30, "alice@example.com", "NYC"]113print(f"name={nameAlice}, city={cityNYC} (ignored age and email)")114115# Practical example116print("\nPractical example:")117118def parse_coordinate(coord_str):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str.split(',')))121122coord_str→ 100,200 = "100,200"123x, y = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str}': x={x}, y={y}")output Underscore for ignored values: first=1, third=3 (ignored middle) name=Alice, city=NYC (ignored age and email) Practical example:def parse_coordinate(coord_str):
118def parse_coordinate(coord_str100,200):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str100,200.split(',')))x ← 100, y ← 200, csv_line ← Alice,30,Engineer, name ← Alice, age ← 30
122coord_str = "100,200"123x→ 100, y→ 200 = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str100,200}': x={x100}, y={y200}")125126# Process CSV line127csv_line→ Alice,30,Engineer = "Alice,30,Engineer"128name→ Alice, age→ 30, job→ Engineer = csv_lineAlice,30,Engineer.split(',')129print(f"CSV: name={nameAlice}, age={age30}, job={jobEngineer}")outputParsed '100,200': x=100, y=200 CSV: name=Alice, age=30, job=Engineer
point ← (100, 200), x ← 100, y ← 200, a ← 5, b ← 10, coordinates ← [100, 200, 300]
1"""Basic unpacking examples"""23# Tuple unpacking4print("Tuple unpacking:")56point→ (100, 200) = (100, 200)7x→ 100, y→ 200 = point(100, 200)8print(f"point = {point(100, 200)}")9print(f"x = {x100}, y = {y200}")1011# Swap variables12a→ 5, b→ 10 = 5, 1013print(f"\nBefore swap: a={a5}, b={b10}")14a→ 10, b→ 5 = b, a15print(f"After swap: a={a10}, b={b5}")1617# List unpacking18print("\nList unpacking:")1920coordinates→ [100, 200, 300] = [100, 200, 300]21x→ 100, y→ 200, z→ 300 = coordinates[100, 200, 300]22print(f"coordinates = {coordinates[100, 200, 300]}")23print(f"x={x100}, y={y200}, z={z300}")2425# String unpacking26print("\nString unpacking:")2728name→ Alice = "Alice"29first→ A, second→ l, third→ i, fourth→ c, fifth→ e = nameAlice30print(f"name = '{nameAlice}'")31print(f"Letters: {firstA}, {secondl}, {thirdi}, {fourthc}, {fifthe}")3233# Multiple assignment34print("\nMultiple assignment:")3536# Single line assignment37a→ 1, b→ 2, c→ 3 = 1, 2, 338print(f"a={a1}, b={b2}, c={c3}")3940# From list41values→ [10, 20, 30] = [10, 20, 30]42x→ 10, y→ 20, z→ 30 = values[10, 20, 30]43print(f"x={x10}, y={y20}, z={z30}")4445# Function returns46print("\nFunction returns:")4748def get_user():49 return "Alice", 30, "alice@example.com"5051name, age, email = get_user()52print(f"User: {name}, {age}, {email}")outputTuple unpacking: point = (100, 200) x = 100, y = 200 Before swap: a=5, b=10 After swap: a=10, b=5 List unpacking: coordinates = [100, 200, 300] x=100, y=200, z=300 String unpacking: name = 'Alice' Letters: A, l, i, c, e Multiple assignment: a=1, b=2, c=3 x=10, y=20, z=30 Function returns:name ← Alice, age ← 30, email ← alice@example.com
51name→ Alice, age→ 30, email→ alice@example.com = get_user()52print(f"User: {nameAlice}, {age30}, {emailalice@example.com}")5354def min_max(numbers):55 return min(numbers), max(numbers)5657minimum, maximum = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum}, Max: {maximum}")outputUser: Alice, 30, alice@example.comdef min_max(numbers):
54def min_max(numbers[5, 2, 8, 1, 9]):55 return min(numbers[5, 2, 8, 1, 9]), max(numbers)minimum ← 1, maximum ← 9, fruits ← ['apple', 'banana', 'cherry']
57minimum→ 1, maximum→ 9 = min_max([5, 2, 8, 1, 9])58print(f"Min: {minimum1}, Max: {maximum9}")5960# Enumerate unpacking61print("\nEnumerate unpacking:")6263fruits→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]outputMin: 1, Max: 9 Enumerate unpacking:for index, fruit in enumerate(fruits):
pass 1 of 365for index0, fruitapple in enumerate(fruits['apple', 'banana', 'cherry']):66 print(f" {index0}: {fruitapple}")output 0: appleAll 3 passes — pass 1 is the card above pass indexfruit1 0 apple 2 1 banana 3 2 cherry user ← {'name': 'Bob', 'age': 25, 'city': 'NYC'}
68# Dict items unpacking69print("\nDict items unpacking:")7071user→ {'name': 'Bob', 'age': 25, 'city': 'NYC'} = {"name": "Bob", "age": 25, "city": "NYC"}output Dict items unpacking:for key, value in user.items():
pass 1 of 373for keyname, valueBob in user{'name': 'Bob', 'age': 25, 'city': 'NYC'}.items():74 print(f" {keyname}: {valueBob}")output name: BobAll 3 passes — pass 1 is the card above pass keyvalue1 name Bob 2 age 25 3 city NYC names ← ['Alice', 'Bob', 'Charlie'], scores ← [85, 92, 78]
76# Zip unpacking77print("\nZip unpacking:")7879names→ ['Alice', 'Bob', 'Charlie'] = ["Alice", "Bob", "Charlie"]80scores→ [85, 92, 78] = [85, 92, 78]output Zip unpacking:for name, score in zip(names, scores):
pass 1 of 382for nameAlice, score85 in zip(names['Alice', 'Bob', 'Charlie'], scores[85, 92, 78]):83 print(f" {nameAlice}: {score85}")output Alice: 85All 3 passes — pass 1 is the card above pass namescore1 Alice 85 2 Bob 92 3 Charlie 78 data ← ('Alice', (30, 'alice@example.com')), name ← Alice, age ← 30
85# Nested tuples86print("\nNested tuples:")8788data→ ('Alice', (30, 'alice@example.com')) = ("Alice", (30, "alice@example.com"))89name→ Alice, (age→ 30, email→ alice@example.com) = data('Alice', (30, 'alice@example.com'))90print(f"name={nameAlice}, age={age30}, email={emailalice@example.com}")9192# Error handling93print("\nError handling:")output Nested tuples: name=Alice, age=30, email=alice@example.com Error handling:except ValueError as e:
96 a, b = [1, 2, 3] # Too many values97except ValueError as e:98 print(f"Error: {etoo many values to unpack (expected 2)}")outputError: too many values to unpack (expected 2)except ValueError as e:
101 a, b, c = [1, 2] # Too few values102except ValueError as e:103 print(f"Error: {enot enough values to unpack (expected 3, got 2)}")outputError: not enough values to unpack (expected 3, got 2)first ← 1, _ ← 2, third ← 3, name ← Alice, city ← NYC, coord_str ← 100,200
105# Underscore for ignored values106print("\nUnderscore for ignored values:")107108# Ignore some values109first→ 1, _→ 2, third→ 3 = [1, 2, 3]110print(f"first={first1}, third={third3} (ignored middle)")111112name→ Alice, _→ alice@example.com, _, city→ NYC = ["Alice", 30, "alice@example.com", "NYC"]113print(f"name={nameAlice}, city={cityNYC} (ignored age and email)")114115# Practical example116print("\nPractical example:")117118def parse_coordinate(coord_str):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str.split(',')))121122coord_str→ 100,200 = "100,200"123x, y = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str}': x={x}, y={y}")output Underscore for ignored values: first=1, third=3 (ignored middle) name=Alice, city=NYC (ignored age and email) Practical example:def parse_coordinate(coord_str):
118def parse_coordinate(coord_str100,200):119 """Parse 'x,y' string into tuple"""120 return tuple(map(int, coord_str100,200.split(',')))x ← 100, y ← 200, csv_line ← Alice,30,Engineer, name ← Alice, age ← 30
122coord_str = "100,200"123x→ 100, y→ 200 = parse_coordinate(coord_str100,200)124print(f"Parsed '{coord_str100,200}': x={x100}, y={y200}")125126# Process CSV line127csv_line→ Alice,30,Engineer = "Alice,30,Engineer"128name→ Alice, age→ 30, job→ Engineer = csv_lineAlice,30,Engineer.split(',')129print(f"CSV: name={nameAlice}, age={age30}, job={jobEngineer}")outputParsed '100,200': x=100, y=200 CSV: name=Alice, age=30, job=Engineer
Basic unpacking matches the number of variables to the number of elements in the sequence. It works with tuples, lists, strings, and any iterable.
Extended Unpacking with *
"""Extended unpacking with * operator"""
# Basic * unpacking
print("Basic * unpacking:")
numbers = [1, 2, 3, 4, 5]
# First and rest
first, *rest = numbers
print(f"numbers = {numbers}")
print(f"first = {first}")
print(f"rest = {rest}")
# Last and rest
print("\nLast and rest:")
*beginning, last = numbers
print(f"beginning = {beginning}")
print(f"last = {last}")
# Middle extraction
print("\nMiddle extraction:")
first, *middle, last = numbers
print(f"first = {first}")
print(f"middle = {middle}")
print(f"last = {last}")
# Multiple *rest patterns
print("\nMultiple patterns:")
# First two and rest
a, b, *rest = [1, 2, 3, 4, 5]
print(f"a={a}, b={b}, rest={rest}")
# First, middle, last two
first, *middle, second_last, last = [1, 2, 3, 4, 5, 6]
print(f"first={first}, middle={middle}, second_last={second_last}, last={last}")
# Empty rest
print("\nEmpty rest:")
# Rest can be empty
a, b, *rest = [1, 2]
print(f"a={a}, b={b}, rest={rest} (empty list)")
first, *middle, last = [1, 2]
print(f"first={first}, middle={middle} (empty), last={last}")
# String unpacking
print("\nString unpacking:")
text = "Python"
first, *middle, last = text
print(f"text = '{text}'")
print(f"first = '{first}', middle = {middle}, last = '{last}'")
# Function arguments
print("\nFunction arguments:")
def process(first, *rest):
print(f" First: {first}")
print(f" Rest: {rest}")
process(1, 2, 3, 4, 5)
# Splitting data
print("\nSplitting data:")
# CSV line
csv = "Alice,30,Engineer,NYC,USA"
name, age, *location = csv.split(',')
print(f"name={name}, age={age}, location={location}")
# Log parsing
log = "2024-01-15 10:30:45 ERROR Database connection failed"
date, time, level, *message = log.split()
print(f"level={level}, message={' '.join(message)}")
# Head and tail
print("\nHead and tail:")
def head_tail(items):
"""Get first element and rest"""
if not items:
return None, []
head, *tail = items
return head, tail
numbers = [10, 20, 30, 40]
head, tail = head_tail(numbers)
print(f"head={head}, tail={tail}")
# Process all but first
print("\nProcess all but first:")
# Skip header
data = ["Name,Age,City", "Alice,30,NYC", "Bob,25,LA"]
header, *rows = data
print(f"Header: {header}")
print("Rows:")
for row in rows:
print(f" {row}")
# Nested unpacking
print("\nNested unpacking:")
data = [1, [2, 3, 4], 5]
first, [second, *middle], last = data
print(f"first={first}, second={second}, middle={middle}, last={last}")
# Split into halves
print("\nSplit into halves:")
# Only ONE * allowed per unpacking
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
mid = len(numbers) // 2
first_half = numbers[:mid]
second_half = numbers[mid:]
print(f"first_half={first_half}")
print(f"second_half={second_half}")
# Practical examples
print("\nPractical examples:")
# Parse command with arguments
command = "git commit -m 'Initial commit' --author 'Alice'"
cmd, *args = command.split()
print(f"Command: {cmd}")
print(f"Arguments: {args}")
# Process scores, ignore outliers
scores = [95, 92, 88, 5, 90, 87, 100] # 5 is outlier
sorted_scores = sorted(scores)
lowest, *middle_scores, highest = sorted_scores
print(f"Outliers: {lowest}, {highest}")
print(f"Valid scores: {middle_scores}")
# Unpack with default
def get_values():
return [1] # Only one value
first, *rest = get_values()
rest_with_default = rest if rest else [0]
print(f"first={first}, rest with default={rest_with_default}")
numbers ← [1, 2, 3, 4, 5], first ← 1, rest ← [2, 3, 4, 5], beginning ← [1, 2, 3, 4]
1"""Extended unpacking with * operator"""23# Basic * unpacking4print("Basic * unpacking:")56numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]78# First and rest9first→ 1, *rest→ [2, 3, 4, 5] = numbers[1, 2, 3, 4, 5]10print(f"numbers = {numbers[1, 2, 3, 4, 5]}")11print(f"first = {first1}")12print(f"rest = {rest[2, 3, 4, 5]}")1314# Last and rest15print("\nLast and rest:")1617*beginning→ [1, 2, 3, 4], last→ 5 = numbers[1, 2, 3, 4, 5]18print(f"beginning = {beginning[1, 2, 3, 4]}")19print(f"last = {last5}")2021# Middle extraction22print("\nMiddle extraction:")2324first→ 1, *middle→ [2, 3, 4], last→ 5 = numbers[1, 2, 3, 4, 5]25print(f"first = {first1}")26print(f"middle = {middle[2, 3, 4]}")27print(f"last = {last5}")2829# Multiple *rest patterns30print("\nMultiple patterns:")3132# First two and rest33a→ 1, b→ 2, *rest→ [3, 4, 5] = [1, 2, 3, 4, 5]34print(f"a={a1}, b={b2}, rest={rest[3, 4, 5]}")3536# First, middle, last two37first→ 1, *middle→ [2, 3, 4], second_last→ 5, last→ 6 = [1, 2, 3, 4, 5, 6]38print(f"first={first1}, middle={middle[2, 3, 4]}, second_last={second_last5}, last={last6}")3940# Empty rest41print("\nEmpty rest:")4243# Rest can be empty44a→ 1, b→ 2, *rest→ [] = [1, 2]45print(f"a={a1}, b={b2}, rest={rest[]} (empty list)")4647first→ 1, *middle→ [], last→ 2 = [1, 2]48print(f"first={first1}, middle={middle[]} (empty), last={last2}")4950# String unpacking51print("\nString unpacking:")5253text→ Python = "Python"54first→ P, *middle→ ['y', 't', 'h', 'o'], last→ n = textPython55print(f"text = '{textPython}'")56print(f"first = '{firstP}', middle = {middle['y', 't', 'h', 'o']}, last = '{lastn}'")5758# Function arguments59print("\nFunction arguments:")6061def process(first, *rest):62 print(f" First: {first}")63 print(f" Rest: {rest}")6465process(1, 2, 3, 4, 5)outputBasic * unpacking: numbers = [1, 2, 3, 4, 5] first = 1 rest = [2, 3, 4, 5] Last and rest: beginning = [1, 2, 3, 4] last = 5 Middle extraction: first = 1 middle = [2, 3, 4] last = 5 Multiple patterns: a=1, b=2, rest=[3, 4, 5] first=1, middle=[2, 3, 4], second_last=5, last=6 Empty rest: a=1, b=2, rest=[] (empty list) first=1, middle=[] (empty), last=2 String unpacking: text = 'Python' first = 'P', middle = ['y', 't', 'h', 'o'], last = 'n' Function arguments:def process(first, *rest):
61def process(first1, *rest(2, 3, 4, 5)):62 print(f" First: {first1}")63 print(f" Rest: {rest(2, 3, 4, 5)}")output First: 1 Rest: (2, 3, 4, 5)csv ← Alice,30,Engineer,NYC,USA, name ← Alice, age ← 30, location ← ['Engineer', 'NYC', 'USA']
65process(1, 2, 3, 4, 5)6667# Splitting data68print("\nSplitting data:")6970# CSV line71csv→ Alice,30,Engineer,NYC,USA = "Alice,30,Engineer,NYC,USA"72name→ Alice, age→ 30, *location→ ['Engineer', 'NYC', 'USA'] = csvAlice,30,Engineer,NYC,USA.split(',')73print(f"name={nameAlice}, age={age30}, location={location['Engineer', 'NYC', 'USA']}")7475# Log parsing76log→ 2024-01-15 10:30:45 ERROR Database connection failed = "2024-01-15 10:30:45 ERROR Database connection failed"77date→ 2024-01-15, time→ 10:30:45, level→ ERROR, *message→ ['Database', 'connection', 'failed'] = log2024-01-15 10:30:45 ERROR Database connection failed.split()78print(f"level={levelERROR}, message={' '.join(message['Database', 'connection', 'failed'])}")7980# Head and tail81print("\nHead and tail:")8283def head_tail(items):84 """Get first element and rest"""85 if not items:86 return None, []87 head, *tail = items88 return head, tail8990numbers→ [10, 20, 30, 40] = [10, 20, 30, 40]91head, tail = head_tail(numbers[10, 20, 30, 40])92print(f"head={head}, tail={tail}")output Splitting data: name=Alice, age=30, location=['Engineer', 'NYC', 'USA'] level=ERROR, message=Database connection failed Head and tail:head ← 10, tail ← [20, 30, 40]
83def head_tail(items[10, 20, 30, 40]):84 """Get first element and rest"""85 if not items:86 return None, []87 head→ 10, *tail→ [20, 30, 40] = items[10, 20, 30, 40]88 return head10, tail[20, 30, 40]head ← 10, tail ← [20, 30, 40], data ← ['Name,Age,City', 'Alice,30,NYC', 'Bob,25,LA']
90numbers = [10, 20, 30, 40]91head→ 10, tail→ [20, 30, 40] = head_tail(numbers[10, 20, 30, 40])92print(f"head={head10}, tail={tail[20, 30, 40]}")9394# Process all but first95print("\nProcess all but first:")9697# Skip header98data→ ['Name,Age,City', 'Alice,30,NYC', 'Bob,25,LA'] = ["Name,Age,City", "Alice,30,NYC", "Bob,25,LA"]99header→ Name,Age,City, *rows→ ['Alice,30,NYC', 'Bob,25,LA'] = data['Name,Age,City', 'Alice,30,NYC', 'Bob,25,LA']100101print(f"Header: {headerName,Age,City}")102print("Rows:")103for row in rows:outputhead=10, tail=[20, 30, 40] Process all but first: Header: Name,Age,City Rows:for row in rows:
pass 1 of 2102print("Rows:")103for rowAlice,30,NYC in rows['Alice,30,NYC', 'Bob,25,LA']:104 print(f" {rowAlice,30,NYC}")output Alice,30,NYCfor row in rows:
pass 2 of 2102print("Rows:")103for rowBob,25,LA in rows['Alice,30,NYC', 'Bob,25,LA']:104 print(f" {rowBob,25,LA}")output Bob,25,LAdata ← [1, [2, 3, 4], 5], first ← 1, second ← 2, middle ← [3, 4]
106# Nested unpacking107print("\nNested unpacking:")108109data→ [1, [2, 3, 4], 5] = [1, [2, 3, 4], 5]110first→ 1, [second→ 2, *middle→ [3, 4]], last→ 5 = data[1, [2, 3, 4], 5]111print(f"first={first1}, second={second2}, middle={middle[3, 4]}, last={last5}")112113# Split into halves114print("\nSplit into halves:")115116# Only ONE * allowed per unpacking117numbers→ [1, 2, 3, 4, 5, 6, 7, 8, 9] = [1, 2, 3, 4, 5, 6, 7, 8, 9]118mid→ 4 = len(numbers[1, 2, 3, 4, 5, 6, 7, 8, 9]) // 2119first_half→ [1, 2, 3, 4] = numbers[:mid][1, 2, 3, 4]120second_half→ [5, 6, 7, 8, 9] = numbers[mid:][5, 6, 7, 8, 9]121print(f"first_half={first_half[1, 2, 3, 4]}")122print(f"second_half={second_half[5, 6, 7, 8, 9]}")123124# Practical examples125print("\nPractical examples:")126127# Parse command with arguments128command→ git commit -m 'Initial commit' --author 'Alice' = "git commit -m 'Initial commit' --author 'Alice'"129cmd→ git, *args→ ['commit', '-m', "'Initial", "commit'", '--author', "'Alice'"] = commandgit commit -m 'Initial commit' --author 'Alice'.split()130print(f"Command: {cmdgit}")131print(f"Arguments: {args['commit', '-m', "'Initial", "commit'", '--author', "'Alice'"]}")132133# Process scores, ignore outliers134scores→ [95, 92, 88, 5, 90, 87, 100] = [95, 92, 88, 5, 90, 87, 100] # 5 is outlier135sorted_scores→ [5, 87, 88, 90, 92, 95, 100] = sorted(scores[95, 92, 88, 5, 90, 87, 100])136lowest→ 5, *middle_scores→ [87, 88, 90, 92, 95], highest→ 100 = sorted_scores[5, 87, 88, 90, 92, 95, 100]137print(f"Outliers: {lowest5}, {highest100}")138print(f"Valid scores: {middle_scores[87, 88, 90, 92, 95]}")139140# Unpack with default141def get_values():142 return [1] # Only one value143144first, *rest = get_values()145rest_with_default = rest if rest else [0]output Nested unpacking: first=1, second=2, middle=[3, 4], last=5 Split into halves: first_half=[1, 2, 3, 4] second_half=[5, 6, 7, 8, 9] Practical examples: Command: git Arguments: ['commit', '-m', "'Initial", "commit'", '--author', "'Alice'"] Outliers: 5, 100 Valid scores: [87, 88, 90, 92, 95]first ← 1, rest ← [], rest_with_default ← [0]
144first→ 1, *rest→ [] = get_values()145rest_with_default→ [0] = rest[] if rest else [0]146print(f"first={first1}, rest with default={rest_with_default[0]}")outputfirst=1, rest with default=[0]
The * operator can appear at the beginning, middle, or end of the unpacking pattern to capture the "rest" of the elements.
Nested Unpacking
"""Nested unpacking examples"""
# Nested tuples
print("Nested tuples:")
person = ("Alice", (30, "alice@example.com"))
name, (age, email) = person
print(f"person = {person}")
print(f"name={name}, age={age}, email={email}")
# Nested lists
print("\nNested lists:")
data = [[1, 2], [3, 4], [5, 6]]
[a, b], [c, d], [e, f] = data
print(f"data = {data}")
print(f"a={a}, b={b}, c={c}, d={d}, e={e}, f={f}")
# Mixed nesting
print("\nMixed nesting:")
record = ("Bob", [25, "NYC"], ("Engineer", 75000))
name, [age, city], (job, salary) = record
print(f"name={name}, age={age}, city={city}, job={job}, salary={salary}")
# Partial nested unpacking
print("\nPartial nested unpacking:")
data = ("Alice", (30, "alice@example.com", "NYC"))
name, info = data
age, email, city = info
print(f"name={name}")
print(f"info={info}")
print(f"age={age}, email={email}, city={city}")
# Nested with *
print("\nNested with *:")
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[first, *rest], middle, last = matrix
print(f"first={first}, rest={rest}")
print(f"middle={middle}")
print(f"last={last}")
# Nested star unpacking
data = [1, [2, 3, 4, 5], 6]
first, [second, *middle, last_inner], last = data
print(f"first={first}, second={second}, middle={middle}, last_inner={last_inner}, last={last}")
# Coordinate pairs
print("\nCoordinate pairs:")
points = [(10, 20), (30, 40), (50, 60)]
for x, y in points:
print(f" Point: ({x}, {y})")
# 3D points
points_3d = [(1, 2, 3), (4, 5, 6)]
for x, y, z in points_3d:
print(f" 3D Point: ({x}, {y}, {z})")
# Nested dict items
print("\nNested dict items:")
users = {
"user1": {"name": "Alice", "age": 30},
"user2": {"name": "Bob", "age": 25}
}
for user_id, user_info in users.items():
name = user_info["name"]
age = user_info["age"]
print(f" {user_id}: {name}, {age}")
# Function returns
print("\nFunction returns:")
def get_stats(numbers):
return min(numbers), (sum(numbers), len(numbers)), max(numbers)
minimum, (total, count), maximum = get_stats([1, 2, 3, 4, 5])
print(f"min={minimum}, total={total}, count={count}, max={maximum}")
print(f"average={total/count}")
# Nested enumerate
print("\nNested enumerate:")
matrix = [[1, 2], [3, 4], [5, 6]]
for i, (a, b) in enumerate(matrix):
print(f" Row {i}: a={a}, b={b}")
# JSON-like structure
print("\nJSON-like structure:")
response = {
"status": 200,
"data": {
"user": {"name": "Alice", "id": 123},
"items": [1, 2, 3]
}
}
# Extract nested values
status = response["status"]
user_data = response["data"]["user"]
name, user_id = user_data["name"], user_data["id"]
print(f"status={status}, user={name} (id={user_id})")
# Complex nesting
print("\nComplex nesting:")
# Table data
table = [
["Name", "Scores"],
["Alice", [85, 90, 92]],
["Bob", [78, 88, 85]]
]
header, *rows = table
[name_col, scores_col] = header
print(f"Columns: {name_col}, {scores_col}")
print("Data:")
for name, scores in rows:
first, *rest = scores
print(f" {name}: first={first}, rest={rest}")
# Tree structure
print("\nTree structure:")
# Binary tree node: (value, left, right)
tree = (5, (3, None, None), (7, (6, None, None), (9, None, None)))
value, left, right = tree
print(f"Root: {value}")
if left:
left_val, _, _ = left
print(f"Left child: {left_val}")
if right:
right_val, right_left, right_right = right
print(f"Right child: {right_val}")
if right_left:
print(f"Right-left grandchild: {right_left[0]}")
# Practical example
print("\nPractical example:")
# Parse nested CSV
csv_data = [
("Alice", "30", "Engineer,Senior,NYC"),
("Bob", "25", "Designer,Junior,LA")
]
for name, age, job_info in csv_data:
job, level, city = job_info.split(',')
print(f" {name} ({age}): {level} {job} in {city}")
# Nested coordinates
regions = [
("North", [(0, 0), (10, 0), (10, 10), (0, 10)]),
("South", [(0, -10), (10, -10), (10, 0), (0, 0)])
]
for region_name, corners in regions:
(x1, y1), (x2, y2), (x3, y3), (x4, y4) = corners
print(f" {region_name}: corners at ({x1},{y1}), ({x2},{y2}), ({x3},{y3}), ({x4},{y4})")
person ← ('Alice', (30, 'alice@example.com')), name ← Alice, age ← 30
1"""Nested unpacking examples"""23# Nested tuples4print("Nested tuples:")56person→ ('Alice', (30, 'alice@example.com')) = ("Alice", (30, "alice@example.com"))7name→ Alice, (age→ 30, email→ alice@example.com) = person('Alice', (30, 'alice@example.com'))8print(f"person = {person('Alice', (30, 'alice@example.com'))}")9print(f"name={nameAlice}, age={age30}, email={emailalice@example.com}")1011# Nested lists12print("\nNested lists:")1314data→ [[1, 2], [3, 4], [5, 6]] = [[1, 2], [3, 4], [5, 6]]15[a→ 1, b→ 2], [c→ 3, d→ 4], [e→ 5, f→ 6] = data[[1, 2], [3, 4], [5, 6]]16print(f"data = {data[[1, 2], [3, 4], [5, 6]]}")17print(f"a={a1}, b={b2}, c={c3}, d={d4}, e={e5}, f={f6}")1819# Mixed nesting20print("\nMixed nesting:")2122record = ("Bob", [25, "NYC"], ("Engineer", 75000))23name→ Bob, [age→ 25, city→ NYC], (job→ Engineer, salary→ 75000) = record('Bob', [25, 'NYC'], ('Engineer', 75000))24print(f"name={nameBob}, age={age25}, city={cityNYC}, job={jobEngineer}, salary={salary75000}")2526# Partial nested unpacking27print("\nPartial nested unpacking:")2829data→ ('Alice', (30, 'alice@example.com', 'NYC')) = ("Alice", (30, "alice@example.com", "NYC"))30name→ Alice, info→ (30, 'alice@example.com', 'NYC') = data('Alice', (30, 'alice@example.com', 'NYC'))31age→ 30, email→ alice@example.com, city→ NYC = info(30, 'alice@example.com', 'NYC')32print(f"name={nameAlice}")33print(f"info={info(30, 'alice@example.com', 'NYC')}")34print(f"age={age30}, email={emailalice@example.com}, city={cityNYC}")3536# Nested with *37print("\nNested with *:")3839matrix→ [[1, 2, 3], [4, 5, 6], [7, 8, 9]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]40[first→ 1, *rest→ [2, 3]], middle→ [4, 5, 6], last→ [7, 8, 9] = matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]41print(f"first={first1}, rest={rest[2, 3]}")42print(f"middle={middle[4, 5, 6]}")43print(f"last={last[7, 8, 9]}")4445# Nested star unpacking46data→ [1, [2, 3, 4, 5], 6] = [1, [2, 3, 4, 5], 6]47first→ 1, [second→ 2, *middle→ [3, 4], last_inner→ 5], last→ 6 = data[1, [2, 3, 4, 5], 6]48print(f"first={first1}, second={second2}, middle={middle[3, 4]}, last_inner={last_inner5}, last={last6}")4950# Coordinate pairs51print("\nCoordinate pairs:")5253points→ [(10, 20), (30, 40), (50, 60)] = [(10, 20), (30, 40), (50, 60)]outputNested tuples: person = ('Alice', (30, 'alice@example.com')) name=Alice, age=30, email=alice@example.com Nested lists: data = [[1, 2], [3, 4], [5, 6]] a=1, b=2, c=3, d=4, e=5, f=6 Mixed nesting: name=Bob, age=25, city=NYC, job=Engineer, salary=75000 Partial nested unpacking: name=Alice info=(30, 'alice@example.com', 'NYC') age=30, email=alice@example.com, city=NYC Nested with *: first=1, rest=[2, 3] middle=[4, 5, 6] last=[7, 8, 9] first=1, second=2, middle=[3, 4], last_inner=5, last=6 Coordinate pairs:for x, y in points:
pass 1 of 355for x10, y20 in points[(10, 20), (30, 40), (50, 60)]:56 print(f" Point: ({x10}, {y20})")output Point: (10, 20)All 3 passes — pass 1 is the card above pass xy1 10 20 2 30 40 3 50 60 points_3d ← [(1, 2, 3), (4, 5, 6)]
58# 3D points59points_3d→ [(1, 2, 3), (4, 5, 6)] = [(1, 2, 3), (4, 5, 6)]60for x, y, z in points_3d:for x, y, z in points_3d:
pass 1 of 259points_3d = [(1, 2, 3), (4, 5, 6)]60for x1, y2, z3 in points_3d[(1, 2, 3), (4, 5, 6)]:61 print(f" 3D Point: ({x1}, {y2}, {z3})")output 3D Point: (1, 2, 3)for x, y, z in points_3d:
pass 2 of 259points_3d = [(1, 2, 3), (4, 5, 6)]60for x4, y5, z6 in points_3d[(1, 2, 3), (4, 5, 6)]:61 print(f" 3D Point: ({x4}, {y5}, {z6})")output 3D Point: (4, 5, 6)users ← {'user1': {'name': 'Alice', 'age': 30}, 'user2': {'name': 'Bob', 'age': 25}}
63# Nested dict items64print("\nNested dict items:")6566users→ {'user1': {'name': 'Alice', 'age': 30}, 'user2': {'name': 'Bob', 'age': 25}} = {67 "user1": {"name": "Alice", "age": 30},68 "user2": {"name": "Bob", "age": 25}69}output Nested dict items:name ← Alice, age ← 30
pass 1 of 271for user_iduser1, user_info{'name': 'Alice', 'age': 30} in users{'user1': {'name': 'Alice', 'age': 30}, 'user2': {'name': 'Bob', 'age': 25}}.items():72 name→ Alice = user_info["name"]Alice73 age→ 30 = user_info["age"]3074 print(f" {user_iduser1}: {nameAlice}, {age30}")output user1: Alice, 30name ← Bob, age ← 25
pass 2 of 271for user_iduser2, user_info{'name': 'Bob', 'age': 25} in users{'user1': {'name': 'Alice', 'age': 30}, 'user2': {'name': 'Bob', 'age': 25}}.items():72 name→ Bob = user_info["name"]Bob73 age→ 25 = user_info["age"]2574 print(f" {user_iduser2}: {nameBob}, {age25}")output user2: Bob, 25print(" Function returns:")
76# Function returns77print("\nFunction returns:")7879def get_stats(numbers):80 return min(numbers), (sum(numbers), len(numbers)), max(numbers)8182minimum, (total, count), maximum = get_stats([1, 2, 3, 4, 5])83print(f"min={minimum}, total={total}, count={count}, max={maximum}")output Function returns:def get_stats(numbers):
79def get_stats(numbers[1, 2, 3, 4, 5]):80 return min(numbers[1, 2, 3, 4, 5]), (sum(numbers), len(numbers)), max(numbers)minimum ← 1, total ← 15, count ← 5, maximum ← 5, matrix ← [[1, 2], [3, 4], [5, 6]]
82minimum→ 1, (total→ 15, count→ 5), maximum→ 5 = get_stats([1, 2, 3, 4, 5])83print(f"min={minimum1}, total={total15}, count={count5}, max={maximum5}")84print(f"average={total15/count5}")8586# Nested enumerate87print("\nNested enumerate:")8889matrix→ [[1, 2], [3, 4], [5, 6]] = [[1, 2], [3, 4], [5, 6]]outputmin=1, total=15, count=5, max=5 average=3.0 Nested enumerate:for i, (a, b) in enumerate(matrix):
pass 1 of 391for i0, (a1, b2) in enumerate(matrix[[1, 2], [3, 4], [5, 6]]):92 print(f" Row {i0}: a={a1}, b={b2}")output Row 0: a=1, b=2All 3 passes — pass 1 is the card above pass iab1 0 1 2 2 1 3 4 3 2 5 6 response ← {'status': 200, 'data': {'user': {'name': 'Alice', 'id': 123}, 'items': [1, 2, 3]}}
94# JSON-like structure95print("\nJSON-like structure:")9697response→ {'status': 200, 'data': {'user': {'name': 'Alice', 'id': 123}, 'items': [1, 2, 3]}} = {98 "status": 200,99 "data": {100 "user": {"name": "Alice", "id": 123},101 "items": [1, 2, 3]102 }103}104105# Extract nested values106status→ 200 = response["status"]200107user_data→ {'name': 'Alice', 'id': 123} = response["data"]["user"]{'name': 'Alice', 'id': 123}108name→ Alice, user_id→ 123 = user_data["name"]Alice, user_data["id"]123109110print(f"status={status200}, user={nameAlice} (id={user_id123})")111112# Complex nesting113print("\nComplex nesting:")114115# Table data116table→ [['Name', 'Scores'], ['Alice', [85, 90, 92]], ['Bob', [78, 88, 85]]] = [117 ["Name", "Scores"],118 ["Alice", [85, 90, 92]],119 ["Bob", [78, 88, 85]]120]121122header→ ['Name', 'Scores'], *rows→ [['Alice', [85, 90, 92]], ['Bob', [78, 88, 85]]] = table[['Name', 'Scores'], ['Alice', [85, 90, 92]], ['Bob', [78, 88, 85]]]123[name_col→ Name, scores_col→ Scores] = header['Name', 'Scores']124125print(f"Columns: {name_colName}, {scores_colScores}")126print("Data:")127for name, scores in rows:output JSON-like structure: status=200, user=Alice (id=123) Complex nesting: Columns: Name, Scores Data:first ← 85, rest ← [90, 92]
pass 1 of 2126print("Data:")127for nameAlice, scores[85, 90, 92] in rows[['Alice', [85, 90, 92]], ['Bob', [78, 88, 85]]]:128 first→ 85, *rest→ [90, 92] = scores[85, 90, 92]129 print(f" {nameAlice}: first={first85}, rest={rest[90, 92]}")output Alice: first=85, rest=[90, 92]first ← 78, rest ← [88, 85]
pass 2 of 2126print("Data:")127for nameBob, scores[78, 88, 85] in rows[['Alice', [85, 90, 92]], ['Bob', [78, 88, 85]]]:128 first→ 78, *rest→ [88, 85] = scores[78, 88, 85]129 print(f" {nameBob}: first={first78}, rest={rest[88, 85]}")output Bob: first=78, rest=[88, 85]tree ← (5, (3, None, None), (7, (6, None, None), (9, None, None)))
131# Tree structure132print("\nTree structure:")133134# Binary tree node: (value, left, right)135tree→ (5, (3, None, None), (7, (6, None, None), (9, None, None))) = (5, (3, None, None), (7, (6, None, None), (9, None, None)))136137value→ 5, left→ (3, None, None), right→ (7, (6, None, None), (9, None, None)) = tree(5, (3, None, None), (7, (6, None, None), (9, None, None)))138print(f"Root: {value5}")output Tree structure: Root: 5left_val ← 3, _ ← None
140if left(3, None, None):141 left_val→ 3, _→ None, _ = left(3, None, None)142 print(f"Left child: {left_val3}")outputLeft child: 3right_val ← 7, right_left ← (6, None, None), right_right ← (9, None, None)
144if right(7, (6, None, None), (9, None, None)):145 right_val→ 7, right_left→ (6, None, None), right_right→ (9, None, None) = right(7, (6, None, None), (9, None, None))146 print(f"Right child: {right_val7}")147 if right_left:outputRight child: 7if right_left:
146print(f"Right child: {right_val}")147if right_left(6, None, None):148 print(f"Right-left grandchild: {right_left[0]6}")outputRight-left grandchild: 6csv_data ← [('Alice', '30', 'Engineer,Senior,NYC'), ('Bob', '25', 'Designer,Junior,LA')]
150# Practical example151print("\nPractical example:")152153# Parse nested CSV154csv_data→ [('Alice', '30', 'Engineer,Senior,NYC'), ('Bob', '25', 'Designer,Junior,LA')] = [155 ("Alice", "30", "Engineer,Senior,NYC"),156 ("Bob", "25", "Designer,Junior,LA")157]output Practical example:job ← Engineer, level ← Senior, city ← NYC
pass 1 of 2159for nameAlice, age30, job_infoEngineer,Senior,NYC in csv_data[('Alice', '30', 'Engineer,Senior,NYC'), ('Bob', '25', 'Designer,Junior,LA')]:160 job→ Engineer, level→ Senior, city→ NYC = job_infoEngineer,Senior,NYC.split(',')161 print(f" {nameAlice} ({age30}): {levelSenior} {jobEngineer} in {cityNYC}")output Alice (30): Senior Engineer in NYCjob ← Designer, level ← Junior, city ← LA
pass 2 of 2159for nameBob, age25, job_infoDesigner,Junior,LA in csv_data[('Alice', '30', 'Engineer,Senior,NYC'), ('Bob', '25', 'Designer,Junior,LA')]:160 job→ Designer, level→ Junior, city→ LA = job_infoDesigner,Junior,LA.split(',')161 print(f" {nameBob} ({age25}): {levelJunior} {jobDesigner} in {cityLA}")output Bob (25): Junior Designer in LAregions ← [('North', [(0, 0), (10, 0), (10, 10), (0, 10)]), ('South', [(0, -10), (10, -10), (10, 0), (0, 0)])]
163# Nested coordinates164regions→ [('North', [(0, 0), (10, 0), (10, 10), (0, 10)]), ('South', [(0, -10), (10, -10), (10, 0), (0, 0)])] = [165 ("North", [(0, 0), (10, 0), (10, 10), (0, 10)]),166 ("South", [(0, -10), (10, -10), (10, 0), (0, 0)])167]x1 ← 0, y1 ← 0, x2 ← 10, y2 ← 0, x3 ← 10, y3 ← 10, x4 ← 0, y4 ← 10
pass 1 of 2169for region_nameNorth, corners[(0, 0), (10, 0), (10, 10), (0, 10)] in regions[('North', [(0, 0), (10, 0), (10, 10), (0, 10)]), ('South', [(0, -10), (10, -10), (10, 0), (0, 0)])]:170 (x1→ 0, y1→ 0), (x2→ 10, y2→ 0), (x3→ 10, y3→ 10), (x4→ 0, y4→ 10) = corners[(0, 0), (10, 0), (10, 10), (0, 10)]171 print(f" {region_nameNorth}: corners at ({x10},{y10}), ({x210},{y20}), ({x310},{y310}), ({x40},{y410})")output North: corners at (0,0), (10,0), (10,10), (0,10)x1 ← 0, y1 ← -10, x2 ← 10, y2 ← -10, x3 ← 10, y3 ← 0, x4 ← 0, y4 ← 0
pass 2 of 2169for region_nameSouth, corners[(0, -10), (10, -10), (10, 0), (0, 0)] in regions[('North', [(0, 0), (10, 0), (10, 10), (0, 10)]), ('South', [(0, -10), (10, -10), (10, 0), (0, 0)])]:170 (x1→ 0, y1→ -10), (x2→ 10, y2→ -10), (x3→ 10, y3→ 0), (x4→ 0, y4→ 0) = corners[(0, -10), (10, -10), (10, 0), (0, 0)]171 print(f" {region_nameSouth}: corners at ({x10},{y1-10}), ({x210},{y2-10}), ({x310},{y30}), ({x40},{y40})")output South: corners at (0,-10), (10,-10), (10,0), (0,0)
Nested unpacking is powerful for extracting data from complex structures like coordinate pairs, database rows, or API responses.
Function Argument Unpacking
"""Function argument unpacking"""
# Basic *args unpacking
print("Basic *args unpacking:")
def add(a, b, c):
return a + b + c
numbers = [1, 2, 3]
result = add(*numbers) # Unpacks list into arguments
print(f"add(*{numbers}) = {result}")
# Tuple unpacking
point = (10, 20, 30)
result = add(*point)
print(f"add(*{point}) = {result}")
# Range unpacking
print("\nRange unpacking:")
# Create range from list
params = [1, 10, 2]
numbers = list(range(*params)) # range(1, 10, 2)
print(f"range(*{params}) = {numbers}")
# Print unpacking
print("\nPrint unpacking:")
# Print all elements
items = ["apple", "banana", "cherry"]
print("Items:", *items)
# Print with separator
print(*items, sep=", ")
print(*items, sep=" | ")
# Variable arguments
print("\nVariable arguments:")
def concatenate(*args):
return "".join(args)
words = ["Hello", " ", "World"]
result = concatenate(*words)
print(f"concatenate(*{words}) = '{result}'")
# **kwargs unpacking
print("\n**kwargs unpacking:")
def greet(name, age, city):
return f"{name}, {age} years old, from {city}"
user = {"name": "Alice", "age": 30, "city": "NYC"}
message = greet(**user) # Unpacks dict into keyword arguments
print(f"greet(**user) = {message}")
# Partial kwargs
print("\nPartial kwargs:")
def create_user(name, age=18, city="Unknown"):
return {"name": name, "age": age, "city": city}
# Provide some kwargs
info = {"age": 25, "city": "LA"}
user = create_user("Bob", **info)
print(f"User: {user}")
# Merging dicts
print("\nMerging dicts:")
defaults = {"host": "localhost", "port": 8080, "debug": False}
overrides = {"port": 3000, "debug": True}
# Merge using **
config = {**defaults, **overrides}
print(f"defaults: {defaults}")
print(f"overrides: {overrides}")
print(f"merged: {config}")
# Function with *args and **kwargs
print("\nFunction with *args and **kwargs:")
def process(*args, **kwargs):
print(f" args: {args}")
print(f" kwargs: {kwargs}")
values = [1, 2, 3]
options = {"mode": "fast", "verbose": True}
process(*values, **options)
# Combining unpacking
print("\nCombining unpacking:")
def calculate(a, b, c, operation="add", precision=2):
if operation == "add":
result = a + b + c
elif operation == "multiply":
result = a * b * c
return round(result, precision)
numbers = [2, 3, 4]
options = {"operation": "multiply", "precision": 1}
result = calculate(*numbers, **options)
print(f"calculate(*{numbers}, **{options}) = {result}")
# String formatting
print("\nString formatting:")
template = "{name} is {age} years old and lives in {city}"
data = {"name": "Alice", "age": 30, "city": "NYC"}
formatted = template.format(**data)
print(f"Formatted: {formatted}")
# Constructor unpacking
print("\nConstructor unpacking:")
class Point:
def __init__(self, x, y, z=0):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return f"Point({self.x}, {self.y}, {self.z})"
# From tuple
coords = (10, 20)
p1 = Point(*coords)
print(f"p1 = {p1}")
# From dict
coords_dict = {"x": 5, "y": 15, "z": 25}
p2 = Point(**coords_dict)
print(f"p2 = {p2}")
# Forwarding arguments
print("\nForwarding arguments:")
def logged_function(func):
def wrapper(*args, **kwargs):
print(f" Calling {func.__name__} with args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f" Result: {result}")
return result
return wrapper
@logged_function
def add_numbers(a, b, c=0):
return a + b + c
add_numbers(1, 2, c=3)
# API calls
print("\nAPI calls:")
def make_request(url, method="GET", headers=None, params=None):
print(f" {method} {url}")
if headers:
print(f" Headers: {headers}")
if params:
print(f" Params: {params}")
request_config = {
"method": "POST",
"headers": {"Content-Type": "application/json"},
"params": {"key": "value"}
}
make_request("https://api.example.com/users", **request_config)
# Practical example
print("\nPractical example:")
# Database query builder
def build_query(table, fields=None, where=None, limit=None):
query = f"SELECT "
query += ", ".join(fields) if fields else "*"
query += f" FROM {table}"
if where:
conditions = " AND ".join(f"{k}='{v}'" for k, v in where.items())
query += f" WHERE {conditions}"
if limit:
query += f" LIMIT {limit}"
return query
# Build query with unpacking
query_params = {
"fields": ["name", "email"],
"where": {"age": 30, "city": "NYC"},
"limit": 10
}
query = build_query("users", **query_params)
print(f"Query: {query}")
numbers ← [1, 2, 3]
1"""Function argument unpacking"""23# Basic *args unpacking4print("Basic *args unpacking:")56def add(a, b, c):7 return a + b + c89numbers→ [1, 2, 3] = [1, 2, 3]10result = add(*numbers[1, 2, 3]) # Unpacks list into arguments11print(f"add(*{numbers}) = {result}")outputBasic *args unpacking:def add(a, b, c):
pass 1 of 26def add(a1, b2, c3):7 return a1 + b2 + c3result ← 6, point ← (10, 20, 30)
9numbers = [1, 2, 3]10result→ 6 = add(*numbers[1, 2, 3]) # Unpacks list into arguments11print(f"add(*{numbers[1, 2, 3]}) = {result6}")1213# Tuple unpacking14point→ (10, 20, 30) = (10, 20, 30)15result = add(*point(10, 20, 30))16print(f"add(*{point}) = {result}")outputadd(*[1, 2, 3]) = 6def add(a, b, c):
pass 2 of 26def add(a10, b20, c30):7 return a10 + b20 + c30result ← 60, params ← [1, 10, 2], numbers ← [1, 3, 5, 7, 9], items ← ['apple', 'banana', 'cherry']
14point = (10, 20, 30)15result→ 60 = add(*point(10, 20, 30))16print(f"add(*{point(10, 20, 30)}) = {result60}")1718# Range unpacking19print("\nRange unpacking:")2021# Create range from list22params→ [1, 10, 2] = [1, 10, 2]23numbers→ [1, 3, 5, 7, 9] = list(range(*params[1, 10, 2])) # range(1, 10, 2)24print(f"range(*{params[1, 10, 2]}) = {numbers[1, 3, 5, 7, 9]}")2526# Print unpacking27print("\nPrint unpacking:")2829# Print all elements30items→ ['apple', 'banana', 'cherry'] = ["apple", "banana", "cherry"]31print("Items:", *items['apple', 'banana', 'cherry'])3233# Print with separator34print(*items['apple', 'banana', 'cherry'], sep=", ")35print(*items['apple', 'banana', 'cherry'], sep=" | ")3637# Variable arguments38print("\nVariable arguments:")3940def concatenate(*args):41 return "".join(args)4243words→ ['Hello', ' ', 'World'] = ["Hello", " ", "World"]44result = concatenate(*words['Hello', ' ', 'World'])45print(f"concatenate(*{words}) = '{result}'")outputadd(*(10, 20, 30)) = 60 Range unpacking: range(*[1, 10, 2]) = [1, 3, 5, 7, 9] Print unpacking: Items: apple banana cherry apple banana cherry apple banana cherry Variable arguments:def concatenate(*args):
40def concatenate(*args('Hello', ' ', 'World')):41 return "".join(args('Hello', ' ', 'World'))result ← Hello World, user ← {'name': 'Alice', 'age': 30, 'city': 'NYC'}
43words = ["Hello", " ", "World"]44result→ Hello World = concatenate(*words['Hello', ' ', 'World'])45print(f"concatenate(*{words['Hello', ' ', 'World']}) = '{resultHello World}'")4647# **kwargs unpacking48print("\n**kwargs unpacking:")4950def greet(name, age, city):51 return f"{name}, {age} years old, from {city}"5253user→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = {"name": "Alice", "age": 30, "city": "NYC"}54message = greet(**user{'name': 'Alice', 'age': 30, 'city': 'NYC'}) # Unpacks dict into keyword arguments55print(f"greet(**user) = {message}")outputconcatenate(*['Hello', ' ', 'World']) = 'Hello World' **kwargs unpacking:def greet(name, age, city):
50def greet(nameAlice, age30, cityNYC):51 return f"{nameAlice}, {age30} years old, from {cityNYC}"message ← Alice, 30 years old, from NYC, info ← {'age': 25, 'city': 'LA'}
53user = {"name": "Alice", "age": 30, "city": "NYC"}54message→ Alice, 30 years old, from NYC = greet(**user{'name': 'Alice', 'age': 30, 'city': 'NYC'}) # Unpacks dict into keyword arguments55print(f"greet(**user) = {messageAlice, 30 years old, from NYC}")5657# Partial kwargs58print("\nPartial kwargs:")5960def create_user(name, age=18, city="Unknown"):61 return {"name": name, "age": age, "city": city}6263# Provide some kwargs64info→ {'age': 25, 'city': 'LA'} = {"age": 25, "city": "LA"}65user = create_user("Bob", **info{'age': 25, 'city': 'LA'})66print(f"User: {user}")outputgreet(**user) = Alice, 30 years old, from NYC Partial kwargs:def create_user(name, age=18, city="Unknown"):
60def create_user(nameBob, age25=18, cityLA="Unknown"):61 return {"name": nameBob, "age": age25, "city": cityLA}user ← {'name': 'Bob', 'age': 25, 'city': 'LA'}, defaults ← {'host': 'localhost', 'port': 8080, 'debug': False}
64info = {"age": 25, "city": "LA"}65user→ {'name': 'Bob', 'age': 25, 'city': 'LA'} = create_user("Bob", **info{'age': 25, 'city': 'LA'})66print(f"User: {user{'name': 'Bob', 'age': 25, 'city': 'LA'}}")6768# Merging dicts69print("\nMerging dicts:")7071defaults→ {'host': 'localhost', 'port': 8080, 'debug': False} = {"host": "localhost", "port": 8080, "debug": False}72overrides→ {'port': 3000, 'debug': True} = {"port": 3000, "debug": True}7374# Merge using **75config→ {'host': 'localhost', 'port': 3000, 'debug': True} = {**defaults{'host': 'localhost', 'port': 8080, 'debug': False}, **overrides{'port': 3000, 'debug': True}}76print(f"defaults: {defaults{'host': 'localhost', 'port': 8080, 'debug': False}}")77print(f"overrides: {overrides{'port': 3000, 'debug': True}}")78print(f"merged: {config{'host': 'localhost', 'port': 3000, 'debug': True}}")7980# Function with *args and **kwargs81print("\nFunction with *args and **kwargs:")8283def process(*args, **kwargs):84 print(f" args: {args}")85 print(f" kwargs: {kwargs}")8687values→ [1, 2, 3] = [1, 2, 3]88options→ {'mode': 'fast', 'verbose': True} = {"mode": "fast", "verbose": True}8990process(*values[1, 2, 3], **options{'mode': 'fast', 'verbose': True})outputUser: {'name': 'Bob', 'age': 25, 'city': 'LA'} Merging dicts: defaults: {'host': 'localhost', 'port': 8080, 'debug': False} overrides: {'port': 3000, 'debug': True} merged: {'host': 'localhost', 'port': 3000, 'debug': True} Function with *args and **kwargs:def process(*args, **kwargs):
83def process(*args(1, 2, 3), **kwargs):84 print(f" args: {args(1, 2, 3)}")85 print(f" kwargs: {kwargs{'mode': 'fast', 'verbose': True}}")output args: (1, 2, 3) kwargs: {'mode': 'fast', 'verbose': True}numbers ← [2, 3, 4], options ← {'operation': 'multiply', 'precision': 1}
90process(*values[1, 2, 3], **options{'mode': 'fast', 'verbose': True})9192# Combining unpacking93print("\nCombining unpacking:")9495def calculate(a, b, c, operation="add", precision=2):96 if operation == "add":97 result = a + b + c98 elif operation == "multiply":99 result = a * b * c100 return round(result, precision)101102numbers→ [2, 3, 4] = [2, 3, 4]103options→ {'operation': 'multiply', 'precision': 1} = {"operation": "multiply", "precision": 1}104105result = calculate(*numbers[2, 3, 4], **options{'operation': 'multiply', 'precision': 1})106print(f"calculate(*{numbers}, **{options}) = {result}")output Combining unpacking:def calculate(a, b, c, operation="add", precision=2):
95def calculate(a2, b3, c4, operationmultiply="add", precision1=2):96 if operation == "add":97 result = a + b + cresult ← 24
97 result = a + b + c98elif operationmultiply == "multiply":99 result→ 24 = a2 * b3 * c4100return round(result, precision)return round(result, precision)
99 result = a * b * c100return round(result24, precision1)result ← 24, template ← {name} is {age} years old and lives in {city}
105result→ 24 = calculate(*numbers[2, 3, 4], **options{'operation': 'multiply', 'precision': 1})106print(f"calculate(*{numbers[2, 3, 4]}, **{options{'operation': 'multiply', 'precision': 1}}) = {result24}")107108# String formatting109print("\nString formatting:")110111template→ {name} is {age} years old and lives in {city} = "{name} is {age} years old and lives in {city}"112data→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = {"name": "Alice", "age": 30, "city": "NYC"}113114formatted→ Alice is 30 years old and lives in NYC = template{name} is {age} years old and lives in {city}.format(**data{'name': 'Alice', 'age': 30, 'city': 'NYC'})115print(f"Formatted: {formattedAlice is 30 years old and lives in NYC}")116117# Constructor unpacking118print("\nConstructor unpacking:")119120class Point:121 def __init__(self, x, y, z=0):122 self.x = x123 self.y = y124 self.z = z125 126 def __repr__(self):127 return f"Point({self.x}, {self.y}, {self.z})"128129# From tuple130coords→ (10, 20) = (10, 20)131p1 = Point(*coords(10, 20))132print(f"p1 = {p1}")outputcalculate(*[2, 3, 4], **{'operation': 'multiply', 'precision': 1}) = 24 String formatting: Formatted: Alice is 30 years old and lives in NYC Constructor unpacking:self.x ← 10, self.y ← 20, self.z ← 0
pass 1 of 2120class Point:121 def __init__(self(empty), x10, y20, z0=0):122 self.x→ 10 = x10123 self.y→ 20 = y20124 self.z→ 0 = z0p1 ← Point(10, 20, 0), coords_dict ← {'x': 5, 'y': 15, 'z': 25}
130coords = (10, 20)131p1→ Point(10, 20, 0) = Point(*coords(10, 20))132print(f"p1 = {p1Point(10, 20, 0)}")133134# From dict135coords_dict→ {'x': 5, 'y': 15, 'z': 25} = {"x": 5, "y": 15, "z": 25}136p2 = Point(**coords_dict{'x': 5, 'y': 15, 'z': 25})137print(f"p2 = {p2}")outputp1 = Point(10, 20, 0)self.x ← 5, self.y ← 15, self.z ← 25
pass 2 of 2120class Point:121 def __init__(self(empty), x5, y15, z25=0):122 self.x→ 5 = x5123 self.y→ 15 = y15124 self.z→ 25 = z25p2 ← Point(5, 15, 25)
135coords_dict = {"x": 5, "y": 15, "z": 25}136p2→ Point(5, 15, 25) = Point(**coords_dict{'x': 5, 'y': 15, 'z': 25})137print(f"p2 = {p2Point(5, 15, 25)}")138139# Forwarding arguments140print("\nForwarding arguments:")outputp2 = Point(5, 15, 25) Forwarding arguments:def logged_function(func):
142def logged_function(func⟨function add_numbers A⟩):143 def wrapper(*args, **kwargs):144 print(f" Calling {func.__name__} with args={args}, kwargs={kwargs}")145 result = func(*args, **kwargs)146 print(f" Result: {result}")147 return result148 return wrapper<function logged_function.<locals>.wrapper at ⟨addr B⟩>add_numbers(1, 2, c=3)
154add_numbers(1, 2, c=3)def wrapper(*args, **kwargs):
142def logged_function(func):143 def wrapper(*args(1, 2), **kwargs):144 print(f" Calling {func.__name__add_numbers} with args={args(1, 2)}, kwargs={kwargs{'c': 3}}")145 result = func(*args(1, 2), **kwargs{'c': 3})146 print(f" Result: {result}")output Calling add_numbers with args=(1, 2), kwargs={'c': 3}def add_numbers(a, b, c=0):
150@logged_function151def add_numbers(a1, b2, c3=0):152 return a1 + b2 + c3result ← 6
144 print(f" Calling {func.__name__} with args={args}, kwargs={kwargs}")145 result→ 6 = func(*args(1, 2), **kwargs{'c': 3})146 print(f" Result: {result6}")147 return result6148return wrapperoutput Result: 6request_config ← {'method': 'POST', 'headers': {'Content-Type': 'application/json'}, 'params': {'key': 'value'}}
154add_numbers(1, 2, c=3)155156# API calls157print("\nAPI calls:")158159def make_request(url, method="GET", headers=None, params=None):160 print(f" {method} {url}")161 if headers:162 print(f" Headers: {headers}")163 if params:164 print(f" Params: {params}")165166request_config→ {'method': 'POST', 'headers': {'Content-Type': 'application/json'}, 'params': {'key': 'value'}} = {167 "method": "POST",168 "headers": {"Content-Type": "application/json"},169 "params": {"key": "value"}170}171172make_request("https://api.example.com/users", **request_config{'method': 'POST', 'headers': {'Content-Type': 'application/json'}, 'params': {'key': 'value'}})output API calls:def make_request(url, method="GET", headers=None, params=None):
159def make_request(urlhttps://api.example.com/users, methodPOST="GET", headers{'Content-Type': 'application/json'}=NoneNone, params{'key': 'value'}=None):160 print(f" {methodPOST} {urlhttps://api.example.com/users}")161 if headers:output POST https://api.example.com/usersif headers:
160print(f" {method} {url}")161if headers{'Content-Type': 'application/json'}:162 print(f" Headers: {headers{'Content-Type': 'application/json'}}")163if params:output Headers: {'Content-Type': 'application/json'}if params:
162 print(f" Headers: {headers}")163if params{'key': 'value'}:164 print(f" Params: {params{'key': 'value'}}")output Params: {'key': 'value'}query_params ← {'fields': ['name', 'email'], 'where': {'age': 30, 'city': 'NYC'}, 'limit': 10}
172make_request("https://api.example.com/users", **request_config{'method': 'POST', 'headers': {'Content-Type': 'application/json'}, 'params': {'key': 'value'}})173174# Practical example175print("\nPractical example:")176177# Database query builder178def build_query(table, fields=None, where=None, limit=None):179 query = f"SELECT "180 query += ", ".join(fields) if fields else "*"181 query += f" FROM {table}"182 183 if where:184 conditions = " AND ".join(f"{k}='{v}'" for k, v in where.items())185 query += f" WHERE {conditions}"186 187 if limit:188 query += f" LIMIT {limit}"189 190 return query191192# Build query with unpacking193query_params→ {'fields': ['name', 'email'], 'where': {'age': 30, 'city': 'NYC'}, 'limit': 10} = {194 "fields": ["name", "email"],195 "where": {"age": 30, "city": "NYC"},196 "limit": 10197}198199query = build_query("users", **query_params{'fields': ['name', 'email'], 'where': {'age': 30, 'city': 'NYC'}, 'limit': 10})200print(f"Query: {query}")output Practical example:query ← SELECT
177# Database query builder178def build_query(tableusers, fields['name', 'email']=NoneNone, where{'age': 30, 'city': 'NYC'}=None, limit10=None):179 query→ SELECT = f"SELECT "180 query→ SELECT name, email += ", ".join(fields['name', 'email']) if fields else "*"181 query→ SELECT name, email FROM users += f" FROM {tableusers}"conditions ← age='30' AND city='NYC', query ← SELECT name, email FROM users WHERE age='30' AND city='NYC'
183if where{'age': 30, 'city': 'NYC'}:184 conditions→ age='30' AND city='NYC' = " AND ".join(f"{k(empty)}='{v(empty)}'" for k, v in where{'age': 30, 'city': 'NYC'}.items())185 query→ SELECT name, email FROM users WHERE age='30' AND city='NYC' += f" WHERE {conditionsage='30' AND city='NYC'}"query ← SELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10
187if limit10:188 query→ SELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10 += f" LIMIT {limit10}"return query
190return querySELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10query ← SELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10
199query→ SELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10 = build_query("users", **query_params{'fields': ['name', 'email'], 'where': {'age': 30, 'city': 'NYC'}, 'limit': 10})200print(f"Query: {querySELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10}")outputQuery: SELECT name, email FROM users WHERE age='30' AND city='NYC' LIMIT 10
This pattern is essential for building flexible APIs, decorators, and configuration systems.
Dictionary Unpacking
"""Dictionary unpacking examples"""
# Basic dict unpacking
print("Basic dict unpacking:")
user1 = {"name": "Alice", "age": 30}
user2 = {"city": "NYC", "job": "Engineer"}
# Merge dicts
merged = {**user1, **user2}
print(f"user1: {user1}")
print(f"user2: {user2}")
print(f"merged: {merged}")
# Overwriting values
print("\nOverwriting values:")
defaults = {"host": "localhost", "port": 8080, "debug": False}
custom = {"port": 3000, "timeout": 30}
# Later values overwrite earlier ones
config = {**defaults, **custom}
print(f"defaults: {defaults}")
print(f"custom: {custom}")
print(f"config: {config}")
# Multiple merges
print("\nMultiple merges:")
base = {"a": 1, "b": 2}
middle = {"b": 20, "c": 3}
final = {"c": 30, "d": 4}
# Merge three dicts
result = {**base, **middle, **final}
print(f"base: {base}")
print(f"middle: {middle}")
print(f"final: {final}")
print(f"result: {result}")
# Adding new keys
print("\nAdding new keys:")
user = {"name": "Bob", "age": 25}
# Add new key while merging
updated = {**user, "email": "bob@example.com"}
print(f"original: {user}")
print(f"updated: {updated}")
# Update existing key
modified = {**user, "age": 26}
print(f"modified: {modified}")
# Conditional merging
print("\nConditional merging:")
user = {"name": "Alice", "age": 30}
admin_fields = {"role": "admin", "permissions": ["read", "write"]}
is_admin = True
profile = {
**user,
**(admin_fields if is_admin else {})
}
print(f"profile (admin={is_admin}): {profile}")
is_admin = False
profile = {
**user,
**(admin_fields if is_admin else {})
}
print(f"profile (admin={is_admin}): {profile}")
# Function kwargs
print("\nFunction kwargs:")
def create_config(**kwargs):
defaults = {"host": "localhost", "port": 8080, "debug": False}
return {**defaults, **kwargs}
config1 = create_config(port=3000)
print(f"config1: {config1}")
config2 = create_config(host="0.0.0.0", debug=True)
print(f"config2: {config2}")
# Copying with modification
print("\nCopying with modification:")
original = {"name": "Alice", "age": 30, "city": "NYC"}
# Copy and modify
modified = {**original, "age": 31}
print(f"original: {original}")
print(f"modified: {modified}")
# Remove key (using dict comprehension)
without_age = {k: v for k, v in {**original}.items() if k != "age"}
print(f"without_age: {without_age}")
# Nested dict merging
print("\nNested dict merging:")
# Shallow merge (doesn't merge nested dicts)
dict1 = {"user": {"name": "Alice", "age": 30}}
dict2 = {"user": {"email": "alice@example.com"}}
merged = {**dict1, **dict2}
print(f"Shallow merge: {merged}")
print(" Note: dict2['user'] completely replaced dict1['user']")
# Deep merge (manual)
def deep_merge(dict1, dict2):
result = dict1.copy()
for key, value in dict2.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = deep_merge(result[key], value)
else:
result[key] = value
return result
dict1 = {"user": {"name": "Alice", "age": 30}}
dict2 = {"user": {"email": "alice@example.com"}}
deep_merged = deep_merge(dict1, dict2)
print(f"Deep merge: {deep_merged}")
# Building objects
print("\nBuilding objects:")
class User:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
return f"User({', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())})"
base_user = {"name": "Bob", "age": 25}
user = User(**base_user, city="LA")
print(f"user: {user}")
# Environment variables
print("\nEnvironment variables:")
# Simulating environment variables
env_vars = {"DB_HOST": "localhost", "DB_PORT": "5432"}
default_vars = {"DB_HOST": "127.0.0.1", "DB_PORT": "5432", "DB_NAME": "mydb"}
# Env vars override defaults
config = {**default_vars, **env_vars}
print(f"config: {config}")
# API responses
print("\nAPI responses:")
def make_response(data, **meta):
return {
"data": data,
**meta
}
response1 = make_response({"users": [1, 2, 3]}, status=200)
print(f"response1: {response1}")
response2 = make_response({"error": "Not found"}, status=404, timestamp=1234567890)
print(f"response2: {response2}")
# Practical example
print("\nPractical example:")
# Configuration builder
class Config:
def __init__(self):
self.settings = {}
def add_section(self, name, **settings):
self.settings[name] = {**self.settings.get(name, {}), **settings}
def get(self):
return self.settings
config = Config()
config.add_section("database", host="localhost", port=5432)
config.add_section("database", username="admin", password="secret")
config.add_section("server", host="0.0.0.0", port=8080)
print("Final config:")
for section, settings in config.get().items():
print(f" [{section}]")
for key, value in settings.items():
print(f" {key}={value}")
# Merging user preferences
default_prefs = {
"theme": "light",
"font_size": 12,
"auto_save": True,
"line_numbers": True
}
user_prefs = {
"theme": "dark",
"font_size": 14
}
final_prefs = {**default_prefs, **user_prefs}
print(f"\nFinal preferences: {final_prefs}")
user1 ← {'name': 'Alice', 'age': 30}, user2 ← {'city': 'NYC', 'job': 'Engineer'}
1"""Dictionary unpacking examples"""23# Basic dict unpacking4print("Basic dict unpacking:")56user1→ {'name': 'Alice', 'age': 30} = {"name": "Alice", "age": 30}7user2→ {'city': 'NYC', 'job': 'Engineer'} = {"city": "NYC", "job": "Engineer"}89# Merge dicts10merged→ {'name': 'Alice', 'age': 30, 'city': 'NYC', 'job': 'Engineer'} = {**user1{'name': 'Alice', 'age': 30}, **user2{'city': 'NYC', 'job': 'Engineer'}}11print(f"user1: {user1{'name': 'Alice', 'age': 30}}")12print(f"user2: {user2{'city': 'NYC', 'job': 'Engineer'}}")13print(f"merged: {merged{'name': 'Alice', 'age': 30, 'city': 'NYC', 'job': 'Engineer'}}")1415# Overwriting values16print("\nOverwriting values:")1718defaults→ {'host': 'localhost', 'port': 8080, 'debug': False} = {"host": "localhost", "port": 8080, "debug": False}19custom→ {'port': 3000, 'timeout': 30} = {"port": 3000, "timeout": 30}2021# Later values overwrite earlier ones22config→ {'host': 'localhost', 'port': 3000, 'debug': False, 'timeout': 30} = {**defaults{'host': 'localhost', 'port': 8080, 'debug': False}, **custom{'port': 3000, 'timeout': 30}}23print(f"defaults: {defaults{'host': 'localhost', 'port': 8080, 'debug': False}}")24print(f"custom: {custom{'port': 3000, 'timeout': 30}}")25print(f"config: {config{'host': 'localhost', 'port': 3000, 'debug': False, 'timeout': 30}}")2627# Multiple merges28print("\nMultiple merges:")2930base→ {'a': 1, 'b': 2} = {"a": 1, "b": 2}31middle→ {'b': 20, 'c': 3} = {"b": 20, "c": 3}32final→ {'c': 30, 'd': 4} = {"c": 30, "d": 4}3334# Merge three dicts35result→ {'a': 1, 'b': 20, 'c': 30, 'd': 4} = {**base{'a': 1, 'b': 2}, **middle{'b': 20, 'c': 3}, **final{'c': 30, 'd': 4}}36print(f"base: {base{'a': 1, 'b': 2}}")37print(f"middle: {middle{'b': 20, 'c': 3}}")38print(f"final: {final{'c': 30, 'd': 4}}")39print(f"result: {result{'a': 1, 'b': 20, 'c': 30, 'd': 4}}")4041# Adding new keys42print("\nAdding new keys:")4344user→ {'name': 'Bob', 'age': 25} = {"name": "Bob", "age": 25}4546# Add new key while merging47updated→ {'name': 'Bob', 'age': 25, 'email': 'bob@example.com'} = {**user{'name': 'Bob', 'age': 25}, "email": "bob@example.com"}48print(f"original: {user{'name': 'Bob', 'age': 25}}")49print(f"updated: {updated{'name': 'Bob', 'age': 25, 'email': 'bob@example.com'}}")5051# Update existing key52modified→ {'name': 'Bob', 'age': 26} = {**user{'name': 'Bob', 'age': 25}, "age": 26}53print(f"modified: {modified{'name': 'Bob', 'age': 26}}")5455# Conditional merging56print("\nConditional merging:")5758user→ {'name': 'Alice', 'age': 30} = {"name": "Alice", "age": 30}59admin_fields→ {'role': 'admin', 'permissions': ['read', 'write']} = {"role": "admin", "permissions": ["read", "write"]}6061is_admin→ True = True62profile→ {'name': 'Alice', 'age': 30, 'role': 'admin', 'permissions': ['read', 'write']} = {63 **user{'name': 'Alice', 'age': 30},64 **(admin_fields{'role': 'admin', 'permissions': ['read', 'write']} if is_adminTrue else {})65}6667print(f"profile (admin={is_adminTrue}): {profile{'name': 'Alice', 'age': 30, 'role': 'admin', 'permissions': ['read', 'write']}}")6869is_admin→ False = False70profile→ {'name': 'Alice', 'age': 30} = {71 **user{'name': 'Alice', 'age': 30},72 **(admin_fields{'role': 'admin', 'permissions': ['read', 'write']} if is_adminFalse else {})73}74print(f"profile (admin={is_adminFalse}): {profile{'name': 'Alice', 'age': 30}}")7576# Function kwargs77print("\nFunction kwargs:")7879def create_config(**kwargs):80 defaults = {"host": "localhost", "port": 8080, "debug": False}81 return {**defaults, **kwargs}8283config1 = create_config(port=3000)84print(f"config1: {config1}")outputBasic dict unpacking: user1: {'name': 'Alice', 'age': 30} user2: {'city': 'NYC', 'job': 'Engineer'} merged: {'name': 'Alice', 'age': 30, 'city': 'NYC', 'job': 'Engineer'} Overwriting values: defaults: {'host': 'localhost', 'port': 8080, 'debug': False} custom: {'port': 3000, 'timeout': 30} config: {'host': 'localhost', 'port': 3000, 'debug': False, 'timeout': 30} Multiple merges: base: {'a': 1, 'b': 2} middle: {'b': 20, 'c': 3} final: {'c': 30, 'd': 4} result: {'a': 1, 'b': 20, 'c': 30, 'd': 4} Adding new keys: original: {'name': 'Bob', 'age': 25} updated: {'name': 'Bob', 'age': 25, 'email': 'bob@example.com'} modified: {'name': 'Bob', 'age': 26} Conditional merging: profile (admin=True): {'name': 'Alice', 'age': 30, 'role': 'admin', 'permissions': ['read', 'write']} profile (admin=False): {'name': 'Alice', 'age': 30} Function kwargs:defaults ← {'host': 'localhost', 'port': 8080, 'debug': False}
pass 1 of 279def create_config(**kwargs):80 defaults→ {'host': 'localhost', 'port': 8080, 'debug': False} = {"host": "localhost", "port": 8080, "debug": False}81 return {**defaults{'host': 'localhost', 'port': 8080, 'debug': False}, **kwargs{'port': 3000}}config1 ← {'host': 'localhost', 'port': 3000, 'debug': False}
83config1→ {'host': 'localhost', 'port': 3000, 'debug': False} = create_config(port=3000)84print(f"config1: {config1{'host': 'localhost', 'port': 3000, 'debug': False}}")8586config2 = create_config(host="0.0.0.0", debug=True)87print(f"config2: {config2}")outputconfig1: {'host': 'localhost', 'port': 3000, 'debug': False}defaults ← {'host': 'localhost', 'port': 8080, 'debug': False}
pass 2 of 279def create_config(**kwargs):80 defaults→ {'host': 'localhost', 'port': 8080, 'debug': False} = {"host": "localhost", "port": 8080, "debug": False}81 return {**defaults{'host': 'localhost', 'port': 8080, 'debug': False}, **kwargs{'host': '0.0.0.0', 'debug': True}}config2 ← {'host': '0.0.0.0', 'port': 8080, 'debug': True}, original ← {'name': 'Alice', 'age': 30, 'city': 'NYC'}
86config2→ {'host': '0.0.0.0', 'port': 8080, 'debug': True} = create_config(host="0.0.0.0", debug=True)87print(f"config2: {config2{'host': '0.0.0.0', 'port': 8080, 'debug': True}}")8889# Copying with modification90print("\nCopying with modification:")9192original→ {'name': 'Alice', 'age': 30, 'city': 'NYC'} = {"name": "Alice", "age": 30, "city": "NYC"}9394# Copy and modify95modified→ {'name': 'Alice', 'age': 31, 'city': 'NYC'} = {**original{'name': 'Alice', 'age': 30, 'city': 'NYC'}, "age": 31}96print(f"original: {original{'name': 'Alice', 'age': 30, 'city': 'NYC'}}")97print(f"modified: {modified{'name': 'Alice', 'age': 31, 'city': 'NYC'}}")9899# Remove key (using dict comprehension)100without_age→ {'name': 'Alice', 'city': 'NYC'} = {k(empty): v(empty) for k, v in {**original{'name': 'Alice', 'age': 30, 'city': 'NYC'}}.items() if k != "age"}101print(f"without_age: {without_age{'name': 'Alice', 'city': 'NYC'}}")102103# Nested dict merging104print("\nNested dict merging:")105106# Shallow merge (doesn't merge nested dicts)107dict1→ {'user': {'name': 'Alice', 'age': 30}} = {"user": {"name": "Alice", "age": 30}}108dict2→ {'user': {'email': 'alice@example.com'}} = {"user": {"email": "alice@example.com"}}109110merged→ {'user': {'email': 'alice@example.com'}} = {**dict1{'user': {'name': 'Alice', 'age': 30}}, **dict2{'user': {'email': 'alice@example.com'}}}111print(f"Shallow merge: {merged{'user': {'email': 'alice@example.com'}}}")112print(" Note: dict2['user'] completely replaced dict1['user']")113114# Deep merge (manual)115def deep_merge(dict1, dict2):116 result = dict1.copy()117 for key, value in dict2.items():118 if key in result and isinstance(result[key], dict) and isinstance(value, dict):119 result[key] = deep_merge(result[key], value)120 else:121 result[key] = value122 return result123124dict1→ {'user': {'name': 'Alice', 'age': 30}} = {"user": {"name": "Alice", "age": 30}}125dict2→ {'user': {'email': 'alice@example.com'}} = {"user": {"email": "alice@example.com"}}126deep_merged = deep_merge(dict1{'user': {'name': 'Alice', 'age': 30}}, dict2{'user': {'email': 'alice@example.com'}})127print(f"Deep merge: {deep_merged}")outputconfig2: {'host': '0.0.0.0', 'port': 8080, 'debug': True} Copying with modification: original: {'name': 'Alice', 'age': 30, 'city': 'NYC'} modified: {'name': 'Alice', 'age': 31, 'city': 'NYC'} without_age: {'name': 'Alice', 'city': 'NYC'} Nested dict merging: Shallow merge: {'user': {'email': 'alice@example.com'}} Note: dict2['user'] completely replaced dict1['user']result ← {'user': {'name': 'Alice', 'age': 30}}
pass 1 of 2114# Deep merge (manual)115def deep_merge(dict1{'user': {'name': 'Alice', 'age': 30}}, dict2{'user': {'email': 'alice@example.com'}}):116 result→ {'user': {'name': 'Alice', 'age': 30}} = dict1{'user': {'name': 'Alice', 'age': 30}}.copy()117 for key, value in dict2.items():for key, value in dict2.items():
pass 1 of 2116result = dict1.copy()117for keyuser, value{'email': 'alice@example.com'} in dict2{'user': {'email': 'alice@example.com'}}.items():118 if key in result and isinstance(result[key], dict) and isinstance(value, dict):119 result[key] = deep_merge(result[key], value)if key in result and isinstance(result[key], dict) and isinstance(valu…
117for key, value in dict2.items():118 if keyuser in result{'user': {'name': 'Alice', 'age': 30}} and isinstance(result[key]{'name': 'Alice', 'age': 30}, dict) and isinstance(value{'email': 'alice@example.com'}, dict):119 result[key] = deep_merge(result[key]{'name': 'Alice', 'age': 30}, value{'email': 'alice@example.com'})120 else:result ← {'name': 'Alice', 'age': 30}
pass 2 of 2114# Deep merge (manual)115def deep_merge(dict1{'name': 'Alice', 'age': 30}, dict2{'email': 'alice@example.com'}):116 result→ {'name': 'Alice', 'age': 30} = dict1{'name': 'Alice', 'age': 30}.copy()117 for key, value in dict2.items():for key, value in dict2.items():
pass 2 of 2116result = dict1.copy()117for keyemail, valuealice@example.com in dict2{'email': 'alice@example.com'}.items():118 if key in result and isinstance(result[key], dict) and isinstance(value, dict):119 result[key] = deep_merge(result[key], value)result[key] ← alice@example.com
118 if key in result and isinstance(result[key], dict) and isinstance(value, dict):119 result[key] = deep_merge(result[key], value)120 else:121 result[key]→ alice@example.com = valuealice@example.com122return resultreturn result
121 result[key] = value122return result{'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}result[key] ← {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}
118if key in result and isinstance(result[key], dict) and isinstance(value, dict):119 result[key]→ {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'} = deep_merge(result[key], value{'email': 'alice@example.com'})120else:return result
121 result[key] = value122return result{'user': {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}}deep_merged ← {'user': {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}}
125dict2 = {"user": {"email": "alice@example.com"}}126deep_merged→ {'user': {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}} = deep_merge(dict1{'user': {'name': 'Alice', 'age': 30}}, dict2{'user': {'email': 'alice@example.com'}})127print(f"Deep merge: {deep_merged{'user': {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}}}")128129# Building objects130print("\nBuilding objects:")131132class User:133 def __init__(self, **kwargs):134 self.__dict__.update(kwargs)135 136 def __repr__(self):137 return f"User({', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())})"138139base_user→ {'name': 'Bob', 'age': 25} = {"name": "Bob", "age": 25}140user = User(**base_user{'name': 'Bob', 'age': 25}, city="LA")141print(f"user: {user}")outputDeep merge: {'user': {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}} Building objects:self.__dict__ ← {'name': 'Bob', 'age': 25, 'city': 'LA'}
132class User:133 def __init__(selfUser(), **kwargs):134 self.__dict__→ {'name': 'Bob', 'age': 25, 'city': 'LA'}.update(kwargs{'name': 'Bob', 'age': 25, 'city': 'LA'})user ← User(name='Bob', age=25, city='LA'), env_vars ← {'DB_HOST': 'localhost', 'DB_PORT': '5432'}
139base_user = {"name": "Bob", "age": 25}140user→ User(name='Bob', age=25, city='LA') = User(**base_user{'name': 'Bob', 'age': 25}, city="LA")141print(f"user: {userUser(name='Bob', age=25, city='LA')}")142143# Environment variables144print("\nEnvironment variables:")145146# Simulating environment variables147env_vars→ {'DB_HOST': 'localhost', 'DB_PORT': '5432'} = {"DB_HOST": "localhost", "DB_PORT": "5432"}148default_vars→ {'DB_HOST': '127.0.0.1', 'DB_PORT': '5432', 'DB_NAME': 'mydb'} = {"DB_HOST": "127.0.0.1", "DB_PORT": "5432", "DB_NAME": "mydb"}149150# Env vars override defaults151config→ {'DB_HOST': 'localhost', 'DB_PORT': '5432', 'DB_NAME': 'mydb'} = {**default_vars{'DB_HOST': '127.0.0.1', 'DB_PORT': '5432', 'DB_NAME': 'mydb'}, **env_vars{'DB_HOST': 'localhost', 'DB_PORT': '5432'}}152print(f"config: {config{'DB_HOST': 'localhost', 'DB_PORT': '5432', 'DB_NAME': 'mydb'}}")153154# API responses155print("\nAPI responses:")156157def make_response(data, **meta):158 return {159 "data": data,160 **meta161 }162163response1 = make_response({"users": [1, 2, 3]}, status=200)164print(f"response1: {response1}")outputuser: User(name='Bob', age=25, city='LA') Environment variables: config: {'DB_HOST': 'localhost', 'DB_PORT': '5432', 'DB_NAME': 'mydb'} API responses:def make_response(data, **meta):
pass 1 of 2157def make_response(data{'users': [1, 2, 3]}, **meta):158 return {159 "data": data{'users': [1, 2, 3]},160 **meta{'status': 200}161 }response1 ← {'data': {'users': [1, 2, 3]}, 'status': 200}
163response1→ {'data': {'users': [1, 2, 3]}, 'status': 200} = make_response({"users": [1, 2, 3]}, status=200)164print(f"response1: {response1{'data': {'users': [1, 2, 3]}, 'status': 200}}")165166response2 = make_response({"error": "Not found"}, status=404, timestamp=1234567890)167print(f"response2: {response2}")outputresponse1: {'data': {'users': [1, 2, 3]}, 'status': 200}def make_response(data, **meta):
pass 2 of 2157def make_response(data{'error': 'Not found'}, **meta):158 return {159 "data": data{'error': 'Not found'},160 **meta{'status': 404, 'timestamp': 1234567890}161 }response2 ← {'data': {'error': 'Not found'}, 'status': 404, 'timestamp': 1234567890}
166response2→ {'data': {'error': 'Not found'}, 'status': 404, 'timestamp': 1234567890} = make_response({"error": "Not found"}, status=404, timestamp=1234567890)167print(f"response2: {response2{'data': {'error': 'Not found'}, 'status': 404, 'timestamp': 1234567890}}")168169# Practical example170print("\nPractical example:")171172# Configuration builder173class Config:174 def __init__(self):175 self.settings = {}176 177 def add_section(self, name, **settings):178 self.settings[name] = {**self.settings.get(name, {}), **settings}179 180 def get(self):181 return self.settings182183config = Config()184config.add_section("database", host="localhost", port=5432)outputresponse2: {'data': {'error': 'Not found'}, 'status': 404, 'timestamp': 1234567890} Practical example:self.settings ← {}
173class Config:174 def __init__(self⟨Config A⟩):175 self.settings→ {} = {}config ← ⟨Config A⟩
183config→ ⟨Config A⟩ = Config()184config⟨Config A⟩.add_section("database", host="localhost", port=5432)185config.add_section("database", username="admin", password="secret")self.settings ← {'database': {'host': 'localhost', 'port': 5432}}
pass 1 of 3177def add_section(self⟨Config A⟩, namedatabase, **settings):178 self.settings[name]→ {'host': 'localhost', 'port': 5432} = {**self.settings→ {'database': {'host': 'localhost', 'port': 5432}}.get(namedatabase, {}), **settings{'host': 'localhost', 'port': 5432}}All 3 passes — pass 1 is the card above pass namesettingsself.settingsself.settings[name]1 database {'host': 'localhost', 'port': 5432} {} → {'database': {'host': 'localhost', 'port': 5432}} {'host': 'localhost', 'port': 5432} 2 database {'username': 'admin', 'password': 'secret'} {'database': {'host': 'localhost', 'port': 5432}} → {'database': {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}} {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} 3 server {'host': '0.0.0.0', 'port': 8080} {'database': {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}} → {'database': {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}, 'server': {'host': '0.0.0.0', 'port': 8080}} {'host': '0.0.0.0', 'port': 8080} config.add_section("database", host="localhost", port=5432)
183config = Config()184config⟨Config A⟩.add_section("database", host="localhost", port=5432)185config⟨Config A⟩.add_section("database", username="admin", password="secret")186config.add_section("server", host="0.0.0.0", port=8080)config.add_section("database", username="admin", password="secret")
184config.add_section("database", host="localhost", port=5432)185config⟨Config A⟩.add_section("database", username="admin", password="secret")186config⟨Config A⟩.add_section("server", host="0.0.0.0", port=8080)config.add_section("server", host="0.0.0.0", port=8080)
185config.add_section("database", username="admin", password="secret")186config⟨Config A⟩.add_section("server", host="0.0.0.0", port=8080)187188print("Final config:")189for section, settings in config.get().items():outputFinal config:def get(self):
180def get(self⟨Config A⟩):181 return self.settings{'database': {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}, 'server': {'host': '0.0.0.0', 'port': 8080}}for section, settings in config.get().items():
pass 1 of 2188print("Final config:")189for sectiondatabase, settings{'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} in config⟨Config A⟩.get().items():190 print(f" [{sectiondatabase}]")191 for key, value in settings.items():output [database]for key, value in settings.items():
pass 1 of 6190print(f" [{section}]")191for keyhost, valuelocalhost in settings{'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'}.items():192 print(f" {keyhost}={valuelocalhost}")output host=localhostAll 6 passes — pass 1 is the card above pass keyvaluesettingssectionconfig1 host localhost {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} — — 2 port 5432 {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} — — 3 username admin {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} — — 4 password secret {'host': 'localhost', 'port': 5432, 'username': 'admin', 'password': 'secret'} server ⟨Config A⟩ 5 host 0.0.0.0 {'host': '0.0.0.0', 'port': 8080} — — 6 port 8080 {'host': '0.0.0.0', 'port': 8080} — — for section, settings in config.get().items():
pass 2 of 2188print("Final config:")189for sectionserver, settings{'host': '0.0.0.0', 'port': 8080} in config⟨Config A⟩.get().items():190 print(f" [{sectionserver}]")191 for key, value in settings.items():output [server]default_prefs ← {'theme': 'light', 'font_size': 12, 'auto_save': True, 'line_numbers': True}
194# Merging user preferences195default_prefs→ {'theme': 'light', 'font_size': 12, 'auto_save': True, 'line_numbers': True} = {196 "theme": "light",197 "font_size": 12,198 "auto_save": True,199 "line_numbers": True200}201202user_prefs→ {'theme': 'dark', 'font_size': 14} = {203 "theme": "dark",204 "font_size": 14205}206207final_prefs→ {'theme': 'dark', 'font_size': 14, 'auto_save': True, 'line_numbers': True} = {**default_prefs{'theme': 'light', 'font_size': 12, 'auto_save': True, 'line_numbers': True}, **user_prefs{'theme': 'dark', 'font_size': 14}}208print(f"\nFinal preferences: {final_prefs{'theme': 'dark', 'font_size': 14, 'auto_save': True, 'line_numbers': True}}")output Final preferences: {'theme': 'dark', 'font_size': 14, 'auto_save': True, 'line_numbers': True}
Dictionary unpacking is the standard way to merge configurations, apply defaults, and build keyword argument sets.
Use Cases
- Swap variables without a temporary:
a, b = b, a - Extract function return values
- Iterate over tuples with
for x, y in pairs - Merge dictionaries:
{**defaults, **overrides} - Forward function arguments with
*args, **kwargs
Exercise: unpacking_practice.py
Parse a CSV line into name, age, and city variables, then merge two config dicts with unpacking