Python Specific
Walrus Operator
When validating input or processing data, you often need to compute a value, check a condition on it, and then use that value. Without the walrus operator, you either repeat the computation or clutter your code with temporary variables. The := operator solves this by combining assignment and expression in one step.
The walrus operator (:=) allows assignment within expressions, introduced in Python 3.8. It assigns values to variables as part of a larger expression, reducing code repetition.
In If Statements
"""Walrus operator in if statements"""
# Basic walrus in if
print("Basic walrus in if:")
# Without walrus
data = [1, 2, 3, 4, 5]
length = len(data)
if length > 3:
print(f"Large list: {length} items")
# With walrus - assign and check in one line
if (n := len(data)) > 3:
print(f"Large list (walrus): {n} items")
# Avoid repeated calls
print("\nAvoid repeated calls:")
def expensive_computation():
print(" Computing...")
return 42
# Without walrus - calls function twice
if expensive_computation() > 40:
result = expensive_computation()
print(f"Result: {result}")
# With walrus - calls function once
if (result := expensive_computation()) > 40:
print(f"Result (walrus): {result}")
# String processing
print("\nString processing:")
text = "Hello World"
# Check length and use it
if (length := len(text)) > 5:
print(f"Long text ({length} chars): {text}")
# Check if text and get first word
if (first_word := text.split()[0] if text else None):
print(f"First word: {first_word}")
# Input validation
print("\nInput validation:")
def get_username():
return "alice"
# Validate and use input
if (username := get_username()) and len(username) >= 3:
print(f"Valid username: {username}")
else:
print("Invalid username")
# Chained conditions
print("\nChained conditions:")
data = {"score": 85, "grade": "B"}
# Check and extract value
if (score := data.get("score")) and score >= 80:
print(f"Good score: {score}")
if (grade := data.get("grade")) and grade in ["A", "B"]:
print(f"Passing grade: {grade}")
# Pattern matching with walrus
print("\nPattern matching with walrus:")
def parse_command(cmd):
parts = cmd.split()
return parts[0] if parts else None
command = "git commit -m 'message'"
if (cmd := parse_command(command)) == "git":
print(f"Git command detected: {command}")
# Nested conditions
print("\nNested conditions:")
user = {"name": "Alice", "profile": {"age": 30}}
# Extract nested value
if (profile := user.get("profile")) and (age := profile.get("age")) >= 18:
print(f"Adult user: {user['name']}, age {age}")
# Range checking
print("\nRange checking:")
numbers = [5, 2, 8, 1, 9, 3, 7]
# Check and use max value
if (max_val := max(numbers)) > 5:
print(f"Max value {max_val} exceeds threshold")
# Check and use min value
if (min_val := min(numbers)) < 3:
print(f"Min value {min_val} below threshold")
# File checking
print("\nFile checking:")
def read_config():
return {"debug": True, "port": 8080}
# Check config and extract value
if (config := read_config()) and config.get("debug"):
print(f"Debug mode enabled (port: {config.get('port')})")
# Practical example
print("\nPractical example:")
# Validate user input
def validate_email(email):
return "@" in email and "." in email
email = "alice@example.com"
if (is_valid := validate_email(email)):
print(f"Email '{email}' is valid")
# Use is_valid later if needed
# Check and process result
def find_user(user_id):
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)
if (user := find_user(1)):
print(f"Found user: {user}")
else:
print("User not found")
# Data processing pipeline
text = " Hello World "
if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:
print(f"Cleaned and checked: '{cleaned}' -> '{upper}'")
"""Walrus operator in if statements"""
# Basic walrus in if
print("Basic walrus in if:")
# Without walrus
data = [1, 2]
length = len(data)
if length > 3:
print(f"Large list: {length} items")
# With walrus - assign and check in one line
if (n := len(data)) > 3:
print(f"Large list (walrus): {n} items")
# Avoid repeated calls
print("\nAvoid repeated calls:")
def expensive_computation():
print(" Computing...")
return 42
# Without walrus - calls function twice
if expensive_computation() > 40:
result = expensive_computation()
print(f"Result: {result}")
# With walrus - calls function once
if (result := expensive_computation()) > 40:
print(f"Result (walrus): {result}")
# String processing
print("\nString processing:")
text = "Hello World"
# Check length and use it
if (length := len(text)) > 5:
print(f"Long text ({length} chars): {text}")
# Check if text and get first word
if (first_word := text.split()[0] if text else None):
print(f"First word: {first_word}")
# Input validation
print("\nInput validation:")
def get_username():
return "alice"
# Validate and use input
if (username := get_username()) and len(username) >= 3:
print(f"Valid username: {username}")
else:
print("Invalid username")
# Chained conditions
print("\nChained conditions:")
data = {"score": 85, "grade": "B"}
# Check and extract value
if (score := data.get("score")) and score >= 80:
print(f"Good score: {score}")
if (grade := data.get("grade")) and grade in ["A", "B"]:
print(f"Passing grade: {grade}")
# Pattern matching with walrus
print("\nPattern matching with walrus:")
def parse_command(cmd):
parts = cmd.split()
return parts[0] if parts else None
command = "git commit -m 'message'"
if (cmd := parse_command(command)) == "git":
print(f"Git command detected: {command}")
# Nested conditions
print("\nNested conditions:")
user = {"name": "Alice", "profile": {"age": 30}}
# Extract nested value
if (profile := user.get("profile")) and (age := profile.get("age")) >= 18:
print(f"Adult user: {user['name']}, age {age}")
# Range checking
print("\nRange checking:")
numbers = [5, 2, 8, 1, 9, 3, 7]
# Check and use max value
if (max_val := max(numbers)) > 5:
print(f"Max value {max_val} exceeds threshold")
# Check and use min value
if (min_val := min(numbers)) < 3:
print(f"Min value {min_val} below threshold")
# File checking
print("\nFile checking:")
def read_config():
return {"debug": True, "port": 8080}
# Check config and extract value
if (config := read_config()) and config.get("debug"):
print(f"Debug mode enabled (port: {config.get('port')})")
# Practical example
print("\nPractical example:")
# Validate user input
def validate_email(email):
return "@" in email and "." in email
email = "alice@example.com"
if (is_valid := validate_email(email)):
print(f"Email '{email}' is valid")
# Use is_valid later if needed
# Check and process result
def find_user(user_id):
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)
if (user := find_user(1)):
print(f"Found user: {user}")
else:
print("User not found")
# Data processing pipeline
text = " Hello World "
if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:
print(f"Cleaned and checked: '{cleaned}' -> '{upper}'")
"""Walrus operator in if statements"""
# Basic walrus in if
print("Basic walrus in if:")
# Without walrus
data = [1, 2, 3, 4, 5, 6]
length = len(data)
if length > 3:
print(f"Large list: {length} items")
# With walrus - assign and check in one line
if (n := len(data)) > 3:
print(f"Large list (walrus): {n} items")
# Avoid repeated calls
print("\nAvoid repeated calls:")
def expensive_computation():
print(" Computing...")
return 42
# Without walrus - calls function twice
if expensive_computation() > 40:
result = expensive_computation()
print(f"Result: {result}")
# With walrus - calls function once
if (result := expensive_computation()) > 40:
print(f"Result (walrus): {result}")
# String processing
print("\nString processing:")
text = "Hello World"
# Check length and use it
if (length := len(text)) > 5:
print(f"Long text ({length} chars): {text}")
# Check if text and get first word
if (first_word := text.split()[0] if text else None):
print(f"First word: {first_word}")
# Input validation
print("\nInput validation:")
def get_username():
return "alice"
# Validate and use input
if (username := get_username()) and len(username) >= 3:
print(f"Valid username: {username}")
else:
print("Invalid username")
# Chained conditions
print("\nChained conditions:")
data = {"score": 85, "grade": "B"}
# Check and extract value
if (score := data.get("score")) and score >= 80:
print(f"Good score: {score}")
if (grade := data.get("grade")) and grade in ["A", "B"]:
print(f"Passing grade: {grade}")
# Pattern matching with walrus
print("\nPattern matching with walrus:")
def parse_command(cmd):
parts = cmd.split()
return parts[0] if parts else None
command = "git commit -m 'message'"
if (cmd := parse_command(command)) == "git":
print(f"Git command detected: {command}")
# Nested conditions
print("\nNested conditions:")
user = {"name": "Alice", "profile": {"age": 30}}
# Extract nested value
if (profile := user.get("profile")) and (age := profile.get("age")) >= 18:
print(f"Adult user: {user['name']}, age {age}")
# Range checking
print("\nRange checking:")
numbers = [5, 2, 8, 1, 9, 3, 7]
# Check and use max value
if (max_val := max(numbers)) > 5:
print(f"Max value {max_val} exceeds threshold")
# Check and use min value
if (min_val := min(numbers)) < 3:
print(f"Min value {min_val} below threshold")
# File checking
print("\nFile checking:")
def read_config():
return {"debug": True, "port": 8080}
# Check config and extract value
if (config := read_config()) and config.get("debug"):
print(f"Debug mode enabled (port: {config.get('port')})")
# Practical example
print("\nPractical example:")
# Validate user input
def validate_email(email):
return "@" in email and "." in email
email = "alice@example.com"
if (is_valid := validate_email(email)):
print(f"Email '{email}' is valid")
# Use is_valid later if needed
# Check and process result
def find_user(user_id):
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)
if (user := find_user(1)):
print(f"Found user: {user}")
else:
print("User not found")
# Data processing pipeline
text = " Hello World "
if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:
print(f"Cleaned and checked: '{cleaned}' -> '{upper}'")
data ← [1, 2, 3, 4, 5], length ← 5
1"""Walrus operator in if statements"""23# Basic walrus in if4print("Basic walrus in if:")56# Without walrus7data→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5] #@data=[1, 2], [1, 2, 3, 4, 5, 6]8length→ 5 = len(data[1, 2, 3, 4, 5])9if length > 3:outputBasic walrus in if:if length > 3:
8length = len(data)9if length5 > 3:10 print(f"Large list: {length5} items")outputLarge list: 5 itemsif (n := len(data)) > 3:
12# With walrus - assign and check in one line13if (n5 := len(data[1, 2, 3, 4, 5])) > 3:14 print(f"Large list (walrus): {n5} items")outputLarge list (walrus): 5 itemsprint(" Avoid repeated calls:")
16# Avoid repeated calls17print("\nAvoid repeated calls:")output Avoid repeated calls:def expensive_computation():
pass 1 of 319def expensive_computation():20 print(" Computing...")21 return 42output Computing...All 3 passes — pass 1 is the card above pass result1 — 2 — 3 42 result ← 42
24if expensive_computation() > 40:25 result→ 42 = expensive_computation()26 print(f"Result: {result42}")outputResult: 42if (result := expensive_computation()) > 40:
28# With walrus - calls function once29if (result42 := expensive_computation()) > 40:30 print(f"Result (walrus): {result42}")outputResult (walrus): 42text ← Hello World
32# String processing33print("\nString processing:")3435text→ Hello World = "Hello World"output String processing:if (length := len(text)) > 5:
37# Check length and use it38if (length11 := len(textHello World)) > 5:39 print(f"Long text ({length11} chars): {textHello World}")outputLong text (11 chars): Hello Worldif (first_word := text.split()[0] if text else None):
41# Check if text and get first word42if (first_wordHello := textHello World.split()[0] if text else None):43 print(f"First word: {first_wordHello}")outputFirst word: Helloprint(" Input validation:")
45# Input validation46print("\nInput validation:")output Input validation:if (username := get_username()) and len(username) >= 3:
51# Validate and use input52if (usernamealice := get_username()) and len(username) >= 3:53 print(f"Valid username: {usernamealice}")54else:outputValid username: alicedata ← {'score': 85, 'grade': 'B'}
57# Chained conditions58print("\nChained conditions:")5960data→ {'score': 85, 'grade': 'B'} = {"score": 85, "grade": "B"}output Chained conditions:if (score := data.get("score")) and score >= 80:
62# Check and extract value63if (score85 := data{'score': 85, 'grade': 'B'}.get("score")) and score >= 80:64 print(f"Good score: {score85}")outputGood score: 85if (grade := data.get("grade")) and grade in ["A", "B"]:
66if (gradeB := data{'score': 85, 'grade': 'B'}.get("grade")) and grade in ["A", "B"]:67 print(f"Passing grade: {gradeB}")outputPassing grade: Bcommand ← git commit -m 'message'
69# Pattern matching with walrus70print("\nPattern matching with walrus:")7172def parse_command(cmd):73 parts = cmd.split()74 return parts[0] if parts else None7576command→ git commit -m 'message' = "git commit -m 'message'"output Pattern matching with walrus:parts ← ['git', 'commit', '-m', "'message'"]
72def parse_command(cmdgit commit -m 'message'):73 parts→ ['git', 'commit', '-m', "'message'"] = cmdgit commit -m 'message'.split()74 return parts[0]git if parts['git', 'commit', '-m', "'message'"] else Noneif (cmd := parse_command(command)) == "git":
78if (cmdgit := parse_command(commandgit commit -m 'message')) == "git":79 print(f"Git command detected: {commandgit commit -m 'message'}")outputGit command detected: git commit -m 'message'user ← {'name': 'Alice', 'profile': {'age': 30}}
81# Nested conditions82print("\nNested conditions:")8384user→ {'name': 'Alice', 'profile': {'age': 30}} = {"name": "Alice", "profile": {"age": 30}}output Nested conditions:if (profile := user.get("profile")) and (age := profile.get("age")) >=…
86# Extract nested value87if (profile{'age': 30} := user{'name': 'Alice', 'profile': {'age': 30}}.get("profile")) and (age30 := profile.get("age")) >= 18:88 print(f"Adult user: {user['name']Alice}, age {age30}")outputAdult user: Alice, age 30numbers ← [5, 2, 8, 1, 9, 3, 7]
90# Range checking91print("\nRange checking:")9293numbers→ [5, 2, 8, 1, 9, 3, 7] = [5, 2, 8, 1, 9, 3, 7]output Range checking:if (max_val := max(numbers)) > 5:
95# Check and use max value96if (max_val9 := max(numbers[5, 2, 8, 1, 9, 3, 7])) > 5:97 print(f"Max value {max_val9} exceeds threshold")outputMax value 9 exceeds thresholdif (min_val := min(numbers)) < 3:
99# Check and use min value100if (min_val1 := min(numbers[5, 2, 8, 1, 9, 3, 7])) < 3:101 print(f"Min value {min_val1} below threshold")outputMin value 1 below thresholdprint(" File checking:")
103# File checking104print("\nFile checking:")output File checking:if (config := read_config()) and config.get("debug"):
109# Check config and extract value110if (config{'debug': True, 'port': 8080} := read_config()) and config.get("debug"):111 print(f"Debug mode enabled (port: {config{'debug': True, 'port': 8080}.get('port')})")outputDebug mode enabled (port: 8080)email ← alice@example.com
113# Practical example114print("\nPractical example:")115116# Validate user input117def validate_email(email):118 return "@" in email and "." in email119120email→ alice@example.com = "alice@example.com"121if (is_valid := validate_email(email)):output Practical example:def validate_email(email):
116# Validate user input117def validate_email(emailalice@example.com):118 return "@" in emailalice@example.com and "." in emailif (is_valid := validate_email(email)):
120email = "alice@example.com"121if (is_validTrue := validate_email(emailalice@example.com)):122 print(f"Email '{emailalice@example.com}' is valid")123 # Use is_valid later if neededoutputEmail 'alice@example.com' is validusers ← {1: 'Alice', 2: 'Bob'}
125# Check and process result126def find_user(user_id1):127 users→ {1: 'Alice', 2: 'Bob'} = {1: "Alice", 2: "Bob"}128 return users{1: 'Alice', 2: 'Bob'}.get(user_id1)if (user := find_user(1)):
130if (userAlice := find_user(1)):131 print(f"Found user: {userAlice}")132else:outputFound user: Alicetext ← Hello World
135# Data processing pipeline136text→ Hello World = " Hello World "137if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned…
136text = " Hello World "137if (cleanedHello World := text Hello World .strip()) and (upperHELLO WORLD := cleaned.upper()) != cleaned:138 print(f"Cleaned and checked: '{cleanedHello World}' -> '{upperHELLO WORLD}'")outputCleaned and checked: 'Hello World' -> 'HELLO WORLD'
data ← [1, 2], length ← 2
1"""Walrus operator in if statements"""23# Basic walrus in if4print("Basic walrus in if:")56# Without walrus7data→ [1, 2] = [1, 2]8length→ 2 = len(data[1, 2])9if length > 3:10 print(f"Large list: {length} items")1112# With walrus - assign and check in one line13if (n := len(data)) > 3:14 print(f"Large list (walrus): {n} items")1516# Avoid repeated calls17print("\nAvoid repeated calls:")outputBasic walrus in if: Avoid repeated calls:def expensive_computation():
pass 1 of 319def expensive_computation():20 print(" Computing...")21 return 42output Computing...All 3 passes — pass 1 is the card above pass result1 — 2 — 3 42 result ← 42
24if expensive_computation() > 40:25 result→ 42 = expensive_computation()26 print(f"Result: {result42}")outputResult: 42if (result := expensive_computation()) > 40:
28# With walrus - calls function once29if (result42 := expensive_computation()) > 40:30 print(f"Result (walrus): {result42}")outputResult (walrus): 42text ← Hello World
32# String processing33print("\nString processing:")3435text→ Hello World = "Hello World"output String processing:if (length := len(text)) > 5:
37# Check length and use it38if (length11 := len(textHello World)) > 5:39 print(f"Long text ({length11} chars): {textHello World}")outputLong text (11 chars): Hello Worldif (first_word := text.split()[0] if text else None):
41# Check if text and get first word42if (first_wordHello := textHello World.split()[0] if text else None):43 print(f"First word: {first_wordHello}")outputFirst word: Helloprint(" Input validation:")
45# Input validation46print("\nInput validation:")output Input validation:if (username := get_username()) and len(username) >= 3:
51# Validate and use input52if (usernamealice := get_username()) and len(username) >= 3:53 print(f"Valid username: {usernamealice}")54else:outputValid username: alicedata ← {'score': 85, 'grade': 'B'}
57# Chained conditions58print("\nChained conditions:")5960data→ {'score': 85, 'grade': 'B'} = {"score": 85, "grade": "B"}output Chained conditions:if (score := data.get("score")) and score >= 80:
62# Check and extract value63if (score85 := data{'score': 85, 'grade': 'B'}.get("score")) and score >= 80:64 print(f"Good score: {score85}")outputGood score: 85if (grade := data.get("grade")) and grade in ["A", "B"]:
66if (gradeB := data{'score': 85, 'grade': 'B'}.get("grade")) and grade in ["A", "B"]:67 print(f"Passing grade: {gradeB}")outputPassing grade: Bcommand ← git commit -m 'message'
69# Pattern matching with walrus70print("\nPattern matching with walrus:")7172def parse_command(cmd):73 parts = cmd.split()74 return parts[0] if parts else None7576command→ git commit -m 'message' = "git commit -m 'message'"output Pattern matching with walrus:parts ← ['git', 'commit', '-m', "'message'"]
72def parse_command(cmdgit commit -m 'message'):73 parts→ ['git', 'commit', '-m', "'message'"] = cmdgit commit -m 'message'.split()74 return parts[0]git if parts['git', 'commit', '-m', "'message'"] else Noneif (cmd := parse_command(command)) == "git":
78if (cmdgit := parse_command(commandgit commit -m 'message')) == "git":79 print(f"Git command detected: {commandgit commit -m 'message'}")outputGit command detected: git commit -m 'message'user ← {'name': 'Alice', 'profile': {'age': 30}}
81# Nested conditions82print("\nNested conditions:")8384user→ {'name': 'Alice', 'profile': {'age': 30}} = {"name": "Alice", "profile": {"age": 30}}output Nested conditions:if (profile := user.get("profile")) and (age := profile.get("age")) >=…
86# Extract nested value87if (profile{'age': 30} := user{'name': 'Alice', 'profile': {'age': 30}}.get("profile")) and (age30 := profile.get("age")) >= 18:88 print(f"Adult user: {user['name']Alice}, age {age30}")outputAdult user: Alice, age 30numbers ← [5, 2, 8, 1, 9, 3, 7]
90# Range checking91print("\nRange checking:")9293numbers→ [5, 2, 8, 1, 9, 3, 7] = [5, 2, 8, 1, 9, 3, 7]output Range checking:if (max_val := max(numbers)) > 5:
95# Check and use max value96if (max_val9 := max(numbers[5, 2, 8, 1, 9, 3, 7])) > 5:97 print(f"Max value {max_val9} exceeds threshold")outputMax value 9 exceeds thresholdif (min_val := min(numbers)) < 3:
99# Check and use min value100if (min_val1 := min(numbers[5, 2, 8, 1, 9, 3, 7])) < 3:101 print(f"Min value {min_val1} below threshold")outputMin value 1 below thresholdprint(" File checking:")
103# File checking104print("\nFile checking:")output File checking:if (config := read_config()) and config.get("debug"):
109# Check config and extract value110if (config{'debug': True, 'port': 8080} := read_config()) and config.get("debug"):111 print(f"Debug mode enabled (port: {config{'debug': True, 'port': 8080}.get('port')})")outputDebug mode enabled (port: 8080)email ← alice@example.com
113# Practical example114print("\nPractical example:")115116# Validate user input117def validate_email(email):118 return "@" in email and "." in email119120email→ alice@example.com = "alice@example.com"121if (is_valid := validate_email(email)):output Practical example:def validate_email(email):
116# Validate user input117def validate_email(emailalice@example.com):118 return "@" in emailalice@example.com and "." in emailif (is_valid := validate_email(email)):
120email = "alice@example.com"121if (is_validTrue := validate_email(emailalice@example.com)):122 print(f"Email '{emailalice@example.com}' is valid")123 # Use is_valid later if neededoutputEmail 'alice@example.com' is validusers ← {1: 'Alice', 2: 'Bob'}
125# Check and process result126def find_user(user_id1):127 users→ {1: 'Alice', 2: 'Bob'} = {1: "Alice", 2: "Bob"}128 return users{1: 'Alice', 2: 'Bob'}.get(user_id1)if (user := find_user(1)):
130if (userAlice := find_user(1)):131 print(f"Found user: {userAlice}")132else:outputFound user: Alicetext ← Hello World
135# Data processing pipeline136text→ Hello World = " Hello World "137if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned…
136text = " Hello World "137if (cleanedHello World := text Hello World .strip()) and (upperHELLO WORLD := cleaned.upper()) != cleaned:138 print(f"Cleaned and checked: '{cleanedHello World}' -> '{upperHELLO WORLD}'")outputCleaned and checked: 'Hello World' -> 'HELLO WORLD'
data ← [1, 2, 3, 4, 5, 6], length ← 6
1"""Walrus operator in if statements"""23# Basic walrus in if4print("Basic walrus in if:")56# Without walrus7data→ [1, 2, 3, 4, 5, 6] = [1, 2, 3, 4, 5, 6]8length→ 6 = len(data[1, 2, 3, 4, 5, 6])9if length > 3:outputBasic walrus in if:if length > 3:
8length = len(data)9if length6 > 3:10 print(f"Large list: {length6} items")outputLarge list: 6 itemsif (n := len(data)) > 3:
12# With walrus - assign and check in one line13if (n6 := len(data[1, 2, 3, 4, 5, 6])) > 3:14 print(f"Large list (walrus): {n6} items")outputLarge list (walrus): 6 itemsprint(" Avoid repeated calls:")
16# Avoid repeated calls17print("\nAvoid repeated calls:")output Avoid repeated calls:def expensive_computation():
pass 1 of 319def expensive_computation():20 print(" Computing...")21 return 42output Computing...All 3 passes — pass 1 is the card above pass result1 — 2 — 3 42 result ← 42
24if expensive_computation() > 40:25 result→ 42 = expensive_computation()26 print(f"Result: {result42}")outputResult: 42if (result := expensive_computation()) > 40:
28# With walrus - calls function once29if (result42 := expensive_computation()) > 40:30 print(f"Result (walrus): {result42}")outputResult (walrus): 42text ← Hello World
32# String processing33print("\nString processing:")3435text→ Hello World = "Hello World"output String processing:if (length := len(text)) > 5:
37# Check length and use it38if (length11 := len(textHello World)) > 5:39 print(f"Long text ({length11} chars): {textHello World}")outputLong text (11 chars): Hello Worldif (first_word := text.split()[0] if text else None):
41# Check if text and get first word42if (first_wordHello := textHello World.split()[0] if text else None):43 print(f"First word: {first_wordHello}")outputFirst word: Helloprint(" Input validation:")
45# Input validation46print("\nInput validation:")output Input validation:if (username := get_username()) and len(username) >= 3:
51# Validate and use input52if (usernamealice := get_username()) and len(username) >= 3:53 print(f"Valid username: {usernamealice}")54else:outputValid username: alicedata ← {'score': 85, 'grade': 'B'}
57# Chained conditions58print("\nChained conditions:")5960data→ {'score': 85, 'grade': 'B'} = {"score": 85, "grade": "B"}output Chained conditions:if (score := data.get("score")) and score >= 80:
62# Check and extract value63if (score85 := data{'score': 85, 'grade': 'B'}.get("score")) and score >= 80:64 print(f"Good score: {score85}")outputGood score: 85if (grade := data.get("grade")) and grade in ["A", "B"]:
66if (gradeB := data{'score': 85, 'grade': 'B'}.get("grade")) and grade in ["A", "B"]:67 print(f"Passing grade: {gradeB}")outputPassing grade: Bcommand ← git commit -m 'message'
69# Pattern matching with walrus70print("\nPattern matching with walrus:")7172def parse_command(cmd):73 parts = cmd.split()74 return parts[0] if parts else None7576command→ git commit -m 'message' = "git commit -m 'message'"output Pattern matching with walrus:parts ← ['git', 'commit', '-m', "'message'"]
72def parse_command(cmdgit commit -m 'message'):73 parts→ ['git', 'commit', '-m', "'message'"] = cmdgit commit -m 'message'.split()74 return parts[0]git if parts['git', 'commit', '-m', "'message'"] else Noneif (cmd := parse_command(command)) == "git":
78if (cmdgit := parse_command(commandgit commit -m 'message')) == "git":79 print(f"Git command detected: {commandgit commit -m 'message'}")outputGit command detected: git commit -m 'message'user ← {'name': 'Alice', 'profile': {'age': 30}}
81# Nested conditions82print("\nNested conditions:")8384user→ {'name': 'Alice', 'profile': {'age': 30}} = {"name": "Alice", "profile": {"age": 30}}output Nested conditions:if (profile := user.get("profile")) and (age := profile.get("age")) >=…
86# Extract nested value87if (profile{'age': 30} := user{'name': 'Alice', 'profile': {'age': 30}}.get("profile")) and (age30 := profile.get("age")) >= 18:88 print(f"Adult user: {user['name']Alice}, age {age30}")outputAdult user: Alice, age 30numbers ← [5, 2, 8, 1, 9, 3, 7]
90# Range checking91print("\nRange checking:")9293numbers→ [5, 2, 8, 1, 9, 3, 7] = [5, 2, 8, 1, 9, 3, 7]output Range checking:if (max_val := max(numbers)) > 5:
95# Check and use max value96if (max_val9 := max(numbers[5, 2, 8, 1, 9, 3, 7])) > 5:97 print(f"Max value {max_val9} exceeds threshold")outputMax value 9 exceeds thresholdif (min_val := min(numbers)) < 3:
99# Check and use min value100if (min_val1 := min(numbers[5, 2, 8, 1, 9, 3, 7])) < 3:101 print(f"Min value {min_val1} below threshold")outputMin value 1 below thresholdprint(" File checking:")
103# File checking104print("\nFile checking:")output File checking:if (config := read_config()) and config.get("debug"):
109# Check config and extract value110if (config{'debug': True, 'port': 8080} := read_config()) and config.get("debug"):111 print(f"Debug mode enabled (port: {config{'debug': True, 'port': 8080}.get('port')})")outputDebug mode enabled (port: 8080)email ← alice@example.com
113# Practical example114print("\nPractical example:")115116# Validate user input117def validate_email(email):118 return "@" in email and "." in email119120email→ alice@example.com = "alice@example.com"121if (is_valid := validate_email(email)):output Practical example:def validate_email(email):
116# Validate user input117def validate_email(emailalice@example.com):118 return "@" in emailalice@example.com and "." in emailif (is_valid := validate_email(email)):
120email = "alice@example.com"121if (is_validTrue := validate_email(emailalice@example.com)):122 print(f"Email '{emailalice@example.com}' is valid")123 # Use is_valid later if neededoutputEmail 'alice@example.com' is validusers ← {1: 'Alice', 2: 'Bob'}
125# Check and process result126def find_user(user_id1):127 users→ {1: 'Alice', 2: 'Bob'} = {1: "Alice", 2: "Bob"}128 return users{1: 'Alice', 2: 'Bob'}.get(user_id1)if (user := find_user(1)):
130if (userAlice := find_user(1)):131 print(f"Found user: {userAlice}")132else:outputFound user: Alicetext ← Hello World
135# Data processing pipeline136text→ Hello World = " Hello World "137if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned:if (cleaned := text.strip()) and (upper := cleaned.upper()) != cleaned…
136text = " Hello World "137if (cleanedHello World := text Hello World .strip()) and (upperHELLO WORLD := cleaned.upper()) != cleaned:138 print(f"Cleaned and checked: '{cleanedHello World}' -> '{upperHELLO WORLD}'")outputCleaned and checked: 'Hello World' -> 'HELLO WORLD'
The walrus operator shines when you need to capture a value while testing it. Parentheses are usually required around the assignment.
In While Loops
"""Walrus operator in while loops"""
# Basic while with walrus
print("Basic while with walrus:")
# Without walrus
data = [1, 2, 3, 4, 5]
index = 0
while index < len(data):
item = data[index]
print(f" Item: {item}")
index += 1
# With walrus - cleaner iteration pattern
print("\nWith walrus:")
items = iter([10, 20, 30, 40, 50])
while (item := next(items, None)) is not None:
print(f" Item: {item}")
# Reading lines
print("\nReading lines:")
# Simulate file reading
lines = iter(["Line 1", "Line 2", "Line 3", ""])
while (line := next(lines, None)) is not None and line != "":
print(f" Processing: {line}")
# Input loop
print("\nInput loop:")
# Simulate user input
inputs = iter(["hello", "world", "quit"])
def get_input():
return next(inputs, None)
while (user_input := get_input()) != "quit":
if user_input:
print(f" You entered: {user_input}")
# Chunk processing
print("\nChunk processing:")
def read_chunk(data, chunk_size):
"""Generator that yields chunks"""
for i in range(0, len(data), chunk_size):
yield data[i:i + chunk_size]
data = list(range(1, 11))
chunks = read_chunk(data, 3)
while (chunk := next(chunks, None)) is not None:
print(f" Processing chunk: {chunk}")
# Accumulator pattern
print("\nAccumulator pattern:")
numbers = [5, 10, 15, 20, 25, 30]
index = 0
total = 0
while (index < len(numbers)) and ((current := numbers[index]) < 25):
total += current
print(f" Added {current}, total: {total}")
index += 1
# Queue processing
print("\nQueue processing:")
queue = [1, 2, 3, 4, 5]
while queue and (item := queue.pop(0)) < 4:
print(f" Processing: {item}")
print(f"Remaining: {queue}")
# Stream processing
print("\nStream processing:")
def generate_data():
"""Simulate data stream"""
for i in range(1, 6):
yield i * 10
stream = generate_data()
while (value := next(stream, None)) is not None:
if value > 30:
print(f" Value {value} exceeds threshold")
else:
print(f" Value {value} within range")
# Parse until delimiter
print("\nParse until delimiter:")
tokens = iter(["token1", "token2", "STOP", "token3", "token4"])
result = []
while (token := next(tokens, None)) and token != "STOP":
result.append(token)
print(f"Tokens before STOP: {result}")
# Buffer reading
print("\nBuffer reading:")
buffer = [b'Hello', b' ', b'World', b'']
output = []
while (chunk := buffer.pop(0) if buffer else None):
output.append(chunk)
print(f"Read: {b''.join(output).decode()}")
# Practical example
print("\nPractical example:")
# Process commands until exit
commands = iter(["print hello", "print world", "count 5", "exit"])
while (cmd := next(commands, None)) and not cmd.startswith("exit"):
parts = cmd.split()
action = parts[0]
if action == "print":
print(f" Output: {' '.join(parts[1:])}")
elif action == "count":
count = int(parts[1])
print(f" Count: {count}")
# Process data with validation
data_stream = iter([{"value": 10}, {"value": 20}, {"value": -1}, {"value": 30}])
total = 0
while (item := next(data_stream, None)) and (val := item.get("value", -1)) >= 0:
total += val
print(f" Added {val}, running total: {total}")
print(f"Final total: {total}")
# Read until condition
numbers = iter([1, 3, 5, 7, 9, 11, 13])
collected = []
while (n := next(numbers, None)) is not None and n < 10:
collected.append(n)
print(f"Collected (< 10): {collected}")
data ← [1, 2, 3, 4, 5], index ← 0
1"""Walrus operator in while loops"""23# Basic while with walrus4print("Basic while with walrus:")56# Without walrus7data→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]8index→ 0 = 09while index < len(data):outputBasic while with walrus:item ← 1, index ← 1
pass 1 of 58index = 09while index0 < len(data[1, 2, 3, 4, 5]):10 item→ 1 = data[index]111 print(f" Item: {item1}")12 index→ 1 += 1output Item: 1All 5 passes — pass 1 is the card above pass data[index]itemindex1 1 1 0 → 1 2 2 2 1 → 2 3 3 3 2 → 3 4 4 4 3 → 4 5 5 5 4 → 5 items ← ⟨list_iterator A⟩
14# With walrus - cleaner iteration pattern15print("\nWith walrus:")16items→ ⟨list_iterator A⟩ = iter([10, 20, 30, 40, 50])17while (item := next(items, None)) is not None:output With walrus:while (item := next(items, None)) is not None:
pass 1 of 516items = iter([10, 20, 30, 40, 50])17while (item10 := next(items⟨list_iterator A⟩, None)) is not None:18 print(f" Item: {item10}")output Item: 10All 5 passes — pass 1 is the card above pass item1 10 2 20 3 30 4 40 5 50 lines ← ⟨list_iterator B⟩
20# Reading lines21print("\nReading lines:")2223# Simulate file reading24lines→ ⟨list_iterator B⟩ = iter(["Line 1", "Line 2", "Line 3", ""])output Reading lines:while (line := next(lines, None)) is not None and line != "":
pass 1 of 326while (lineLine 1 := next(lines⟨list_iterator B⟩, None)) is not None and line != "":27 print(f" Processing: {lineLine 1}")output Processing: Line 1All 3 passes — pass 1 is the card above pass line1 Line 1 2 Line 2 3 Line 3 inputs ← ⟨list_iterator C⟩
29# Input loop30print("\nInput loop:")3132# Simulate user input33inputs→ ⟨list_iterator C⟩ = iter(["hello", "world", "quit"])output Input loop:def get_input():
pass 1 of 335def get_input():36 return next(inputs⟨list_iterator C⟩, None)All 3 passes — pass 1 is the card above pass user_input1 hello 2 world 3 — while (user_input := get_input()) != "quit":
pass 1 of 238while (user_inputhello := get_input()) != "quit":39 if user_input:40 print(f" You entered: {user_input}")if user_input:
pass 1 of 238while (user_input := get_input()) != "quit":39 if user_inputhello:40 print(f" You entered: {user_inputhello}")output You entered: hellowhile (user_input := get_input()) != "quit":
pass 2 of 238while (user_inputworld := get_input()) != "quit":39 if user_input:40 print(f" You entered: {user_input}")if user_input:
pass 2 of 238while (user_input := get_input()) != "quit":39 if user_inputworld:40 print(f" You entered: {user_inputworld}")output You entered: worlddata ← [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], chunks ← ⟨generator object read_chunk D⟩
42# Chunk processing43print("\nChunk processing:")4445def read_chunk(data, chunk_size):46 """Generator that yields chunks"""47 for i in range(0, len(data), chunk_size):48 yield data[i:i + chunk_size]4950data→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = list(range(1, 11))51chunks→ ⟨generator object read_chunk D⟩ = read_chunk(data[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)output Chunk processing:def read_chunk(data, chunk_size):
45def read_chunk(data[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], chunk_size3):46 """Generator that yields chunks"""47 for i in range(0, len(data), chunk_size):for i in range(0, len(data), chunk_size):
pass 1 of 446"""Generator that yields chunks"""47for i0 in range(0, len(data[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), chunk_size3):48 yield data[i:i + chunk_size][1, 2, 3]All 4 passes — pass 1 is the card above pass idata[i:i + chunk_size]1 0 [1, 2, 3] 2 3 [4, 5, 6] 3 6 [7, 8, 9] 4 9 [10] while (chunk := next(chunks, None)) is not None:
pass 1 of 447 for i in range(0, len(data), chunk_size):48 yield data[i:i + chunk_size][1, 2, 3]4950data = list(range(1, 11))51chunks = read_chunk(data, 3)5253while (chunk[1, 2, 3] := next(chunks⟨generator object read_chunk D⟩, None)) is not None:54 print(f" Processing chunk: {chunk[1, 2, 3]}")output Processing chunk: [1, 2, 3]All 4 passes — pass 1 is the card above pass chunkdata[i:i + chunk_size]1 [1, 2, 3] [1, 2, 3] 2 [4, 5, 6] [4, 5, 6] 3 [7, 8, 9] [7, 8, 9] 4 [10] [10] numbers ← [5, 10, 15, 20, 25, 30], index ← 0, total ← 0
56# Accumulator pattern57print("\nAccumulator pattern:")5859numbers→ [5, 10, 15, 20, 25, 30] = [5, 10, 15, 20, 25, 30]60index→ 0 = 061total→ 0 = 0output Accumulator pattern:total ← 5, index ← 1
pass 1 of 463while (index0 < len(numbers[5, 10, 15, 20, 25, 30])) and ((current5 := numbers[index]5) < 25):64 total→ 5 += current565 print(f" Added {current5}, total: {total5}")66 index→ 1 += 1output Added 5, total: 5All 4 passes — pass 1 is the card above pass numbers[index]currenttotalindex1 5 5 0 → 5 0 → 1 2 10 10 5 → 15 1 → 2 3 15 15 15 → 30 2 → 3 4 20 20 30 → 50 3 → 4 queue ← [1, 2, 3, 4, 5]
68# Queue processing69print("\nQueue processing:")7071queue→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]output Queue processing:while queue and (item := queue.pop(0)) < 4:
pass 1 of 373while queue[2, 3, 4, 5] and (item1 := queue.pop(0)) < 4:74 print(f" Processing: {item1}")output Processing: 1All 3 passes — pass 1 is the card above pass queueitem1 [2, 3, 4, 5] 1 2 [3, 4, 5] 2 3 [4, 5] 3 stream ← ⟨generator object generate_data E⟩
76print(f"Remaining: {queue[5]}")7778# Stream processing79print("\nStream processing:")8081def generate_data():82 """Simulate data stream"""83 for i in range(1, 6):84 yield i * 108586stream→ ⟨generator object generate_data E⟩ = generate_data()outputRemaining: [5] Stream processing:for i in range(1, 6):
pass 1 of 582"""Simulate data stream"""83for i1 in range(1, 6):84 yield i1 * 10All 5 passes — pass 1 is the card above pass ivalue1 1 — 2 2 — 3 3 — 4 4 40 5 5 50 while (value := next(stream, None)) is not None:
pass 1 of 588while (value10 := next(stream⟨generator object generate_data E⟩, None)) is not None:89 if value > 30:90 print(f" Value {value} exceeds threshold")All 5 passes — pass 1 is the card above pass valuei1 10 — 2 20 — 3 30 — 4 40 4 5 50 5 else:
pass 1 of 383 for i in range(1, 6):84 yield i1 * 108586stream = generate_data()8788while (value := next(stream, None)) is not None:89 if value > 30:90 print(f" Value {value} exceeds threshold")91 else:92 print(f" Value {value10} within range")output Value 10 within rangeAll 3 passes — pass 1 is the card above pass valuei1 10 1 2 20 2 3 30 3 if value > 30:
pass 1 of 283 for i in range(1, 6):84 yield i4 * 108586stream = generate_data()8788while (value := next(stream, None)) is not None:89 if value40 > 30:90 print(f" Value {value40} exceeds threshold")91 else:output Value 40 exceeds thresholdif value > 30:
pass 2 of 283 for i in range(1, 6):84 yield i5 * 108586stream = generate_data()8788while (value := next(stream, None)) is not None:89 if value50 > 30:90 print(f" Value {value50} exceeds threshold")91 else:output Value 50 exceeds thresholdtokens ← ⟨list_iterator F⟩, result ← []
94# Parse until delimiter95print("\nParse until delimiter:")9697tokens→ ⟨list_iterator F⟩ = iter(["token1", "token2", "STOP", "token3", "token4"])9899result→ [] = []100while (token := next(tokens, None)) and token != "STOP":output Parse until delimiter:result ← ['token1']
pass 1 of 299result = []100while (tokentoken1 := next(tokens⟨list_iterator F⟩, None)) and token != "STOP":101 result→ ['token1'].append(tokentoken1)result ← ['token1', 'token2']
pass 2 of 299result = []100while (tokentoken2 := next(tokens⟨list_iterator F⟩, None)) and token != "STOP":101 result→ ['token1', 'token2'].append(tokentoken2)buffer ← [b'Hello', b' ', b'World', b''], output ← []
103print(f"Tokens before STOP: {result['token1', 'token2']}")104105# Buffer reading106print("\nBuffer reading:")107108buffer→ [b'Hello', b' ', b'World', b''] = [b'Hello', b' ', b'World', b'']109110output→ [] = []111while (chunk := buffer.pop(0) if buffer else None):outputTokens before STOP: ['token1', 'token2'] Buffer reading:output ← [b'Hello']
pass 1 of 3110output = []111while (chunkb'Hello' := buffer[b' ', b'World', b''].pop(0) if buffer else None):112 output→ [b'Hello'].append(chunkb'Hello')All 3 passes — pass 1 is the card above pass bufferchunkoutput1 [b' ', b'World', b''] b'Hello' [] → [b'Hello'] 2 [b'World', b''] b' ' [b'Hello'] → [b'Hello', b' '] 3 [b''] b'World' [b'Hello', b' '] → [b'Hello', b' ', b'World'] commands ← ⟨list_iterator G⟩
114print(f"Read: {b''.join(output[b'Hello', b' ', b'World']).decode()}")115116# Practical example117print("\nPractical example:")118119# Process commands until exit120commands→ ⟨list_iterator G⟩ = iter(["print hello", "print world", "count 5", "exit"])outputRead: Hello World Practical example:parts ← ['print', 'hello'], action ← print
pass 1 of 3122while (cmdprint hello := next(commands⟨list_iterator G⟩, None)) and not cmd.startswith("exit"):123 parts→ ['print', 'hello'] = cmdprint hello.split()124 action→ print = parts[0]printAll 3 passes — pass 1 is the card above pass cmdparts[0]parts[1:]parts[1]partsactioncount1 print hello print ['hello'] — ['print', 'hello'] print — 2 print world print ['world'] — ['print', 'world'] print — 3 count 5 count — 5 ['count', '5'] count 5 if action == "print":
pass 1 of 2126if actionprint == "print":127 print(f" Output: {' '.join(parts[1:]['hello'])}")128elif action == "count":output Output: helloif action == "print":
pass 2 of 2126if actionprint == "print":127 print(f" Output: {' '.join(parts[1:]['world'])}")128elif action == "count":output Output: worldcount ← 5
127 print(f" Output: {' '.join(parts[1:])}")128elif actioncount == "count":129 count→ 5 = int(parts[1]5)130 print(f" Count: {count5}")output Count: 5data_stream ← ⟨list_iterator H⟩, total ← 0
132# Process data with validation133data_stream→ ⟨list_iterator H⟩ = iter([{"value": 10}, {"value": 20}, {"value": -1}, {"value": 30}])134135total→ 0 = 0136while (item := next(data_stream, None)) and (val := item.get("value", -1)) >= 0:total ← 10
pass 1 of 2135total = 0136while (item{'value': 10} := next(data_stream⟨list_iterator H⟩, None)) and (val10 := item.get("value", -1)) >= 0:137 total→ 10 += val10138 print(f" Added {val10}, running total: {total10}")output Added 10, running total: 10total ← 30
pass 2 of 2135total = 0136while (item{'value': 20} := next(data_stream⟨list_iterator H⟩, None)) and (val20 := item.get("value", -1)) >= 0:137 total→ 30 += val20138 print(f" Added {val20}, running total: {total30}")output Added 20, running total: 30numbers ← ⟨list_iterator I⟩, collected ← []
140print(f"Final total: {total30}")141142# Read until condition143numbers→ ⟨list_iterator I⟩ = iter([1, 3, 5, 7, 9, 11, 13])144collected→ [] = []outputFinal total: 30collected ← [1]
pass 1 of 5146while (n1 := next(numbers⟨list_iterator I⟩, None)) is not None and n < 10:147 collected→ [1].append(n1)All 5 passes — pass 1 is the card above pass ncollected1 1 [] → [1] 2 3 [1] → [1, 3] 3 5 [1, 3] → [1, 3, 5] 4 7 [1, 3, 5] → [1, 3, 5, 7] 5 9 [1, 3, 5, 7] → [1, 3, 5, 7, 9] print(f"Collected (< 10): {collected}")
149print(f"Collected (< 10): {collected[1, 3, 5, 7, 9]}")outputCollected (< 10): [1, 3, 5, 7, 9]
This pattern replaces the awkward "prime the loop" idiom where you read once before the loop and again inside it.
In Comprehensions
"""Walrus operator in comprehensions"""
# Basic list comprehension
print("Basic list comprehension:")
# Without walrus - compute twice
numbers = [1, 2, 3, 4, 5]
squared = [n * n for n in numbers if n * n > 10]
print(f"Squared (>10): {squared}")
# With walrus - compute once
squared_walrus = [sq for n in numbers if (sq := n * n) > 10]
print(f"Squared walrus: {squared_walrus}")
# Expensive computation
print("\nExpensive computation:")
def process(n):
print(f" Processing {n}")
return n * 10
numbers = [1, 2, 3, 4, 5]
# Without walrus - processes each number twice
result = [process(n) for n in numbers if process(n) > 25]
print(f"Result (called twice): {result}")
# With walrus - processes once
result_walrus = [p for n in numbers if (p := process(n)) > 25]
print(f"Result walrus (called once): {result_walrus}")
# String processing
print("\nString processing:")
words = ["hello", "world", "python", "programming"]
# Get uppercase versions only for words longer than 5
result = [upper for word in words if (upper := word.upper()) and len(word) > 5]
print(f"Long words (uppercase): {result}")
# Data transformation
print("\nData transformation:")
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Square numbers and filter
squared_evens = [sq for n in data if (sq := n * n) % 2 == 0]
print(f"Even squares: {squared_evens}")
# Dict comprehension
print("\nDict comprehension:")
numbers = [1, 2, 3, 4, 5]
# Create dict with computed values
squares_dict = {n: sq for n in numbers if (sq := n * n) < 20}
print(f"Squares dict: {squares_dict}")
# Nested comprehension
print("\nNested comprehension:")
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Flatten and filter with transformation
result = [doubled for row in matrix for item in row if (doubled := item * 2) > 8]
print(f"Filtered doubled: {result}")
# Generator expression
print("\nGenerator expression:")
numbers = range(1, 11)
# Generator with walrus
gen = (sq for n in numbers if (sq := n * n) > 20)
result = list(gen)
print(f"Squares > 20: {result}")
# Any/All with walrus
print("\nAny/All with walrus:")
data = [1, 2, 3, 4, 5]
# Check if any squared value > 20
if any((sq := n * n) > 20 for n in data):
print(f"Found square > 20")
# Get first match with walrus
numbers = [1, 2, 3, 4, 5, 6, 7]
first_big = next((sq for n in numbers if (sq := n * n) > 20), None)
print(f"First square > 20: {first_big}")
# Set comprehension
print("\nSet comprehension:")
words = ["hello", "world", "hello", "python", "world"]
# Get unique lengths
lengths = {ln for word in words if (ln := len(word)) > 4}
print(f"Unique lengths > 4: {lengths}")
# Multiple conditions
print("\nMultiple conditions:")
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Multiple transformations
result = [
doubled
for n in numbers
if (doubled := n * 2) > 5
if (squared := doubled * doubled) < 200
]
print(f"Filtered transformations: {result}")
# Practical example
print("\nPractical example:")
# Process user data
users = [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
]
# Get names of users over 26
names = [name for user in users if (age := user.get("age", 0)) > 26 and (name := user.get("name"))]
print(f"Users over 26: {names}")
# Parse and validate
raw_data = ["10", "20", "abc", "30", "def"]
def try_parse(s):
try:
return int(s)
except ValueError:
return None
# Get valid integers > 15
valid = [num for s in raw_data if (num := try_parse(s)) is not None and num > 15]
print(f"Valid numbers > 15: {valid}")
# File processing simulation
lines = ["# comment", "data: 10", "# ignore", "data: 20", "data: 30"]
# Extract data lines and parse
data_values = [
int(parts[1])
for line in lines
if not line.startswith("#")
if (parts := line.split(": "))
if len(parts) == 2
]
print(f"Data values: {data_values}")
numbers ← [1, 2, 3, 4, 5], squared ← [16, 25], sq ← 25, squared_walrus ← [16, 25]
1"""Walrus operator in comprehensions"""23# Basic list comprehension4print("Basic list comprehension:")56# Without walrus - compute twice7numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]8squared→ [16, 25] = [n * n for n in numbers[1, 2, 3, 4, 5] if n * n > 10]9print(f"Squared (>10): {squared[16, 25]}")1011# With walrus - compute once12squared_walrus→ [16, 25] = [sq→ 25 for n in numbers[1, 2, 3, 4, 5] if (sq := n * n) > 10]13print(f"Squared walrus: {squared_walrus[16, 25]}")1415# Expensive computation16print("\nExpensive computation:")1718def process(n):19 print(f" Processing {n}")20 return n * 102122numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]2324# Without walrus - processes each number twice25result = [process(n) for n in numbers[1, 2, 3, 4, 5] if process(n) > 25]26print(f"Result (called twice): {result}")outputBasic list comprehension: Squared (>10): [16, 25] Squared walrus: [16, 25] Expensive computation:def process(n):
pass 1 of 1318def process(n1):19 print(f" Processing {n1}")20 return n1 * 10output Processing 113 passes — pass 1 is the card above pass n1 1 2 2 3 3 4 3 5 4 6 4 7 5 8 5 9 1 ⋯ 2 more passes ⋯ 12 4 13 5 result ← [30, 40, 50]
24# Without walrus - processes each number twice25result→ [30, 40, 50] = [process(n) for n in numbers[1, 2, 3, 4, 5] if process(n) > 25]26print(f"Result (called twice): {result[30, 40, 50]}")2728# With walrus - processes once29result_walrus = [p(empty) for n in numbers[1, 2, 3, 4, 5] if (p := process(n)) > 25]30print(f"Result walrus (called once): {result_walrus}")outputResult (called twice): [30, 40, 50]p ← 50, result_walrus ← [30, 40, 50], words ← ['hello', 'world', 'python', 'programming']
28# With walrus - processes once29result_walrus→ [30, 40, 50] = [p→ 50 for n in numbers[1, 2, 3, 4, 5] if (p := process(n)) > 25]30print(f"Result walrus (called once): {result_walrus[30, 40, 50]}")3132# String processing33print("\nString processing:")3435words→ ['hello', 'world', 'python', 'programming'] = ["hello", "world", "python", "programming"]3637# Get uppercase versions only for words longer than 538result→ ['PYTHON', 'PROGRAMMING'] = [upper→ PROGRAMMING for word in words['hello', 'world', 'python', 'programming'] if (upper := word.upper()) and len(word) > 5]39print(f"Long words (uppercase): {result['PYTHON', 'PROGRAMMING']}")4041# Data transformation42print("\nData transformation:")4344data→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]4546# Square numbers and filter47squared_evens→ [4, 16, 36, 64, 100] = [sq→ 100 for n in data[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if (sq := n * n) % 2 == 0]48print(f"Even squares: {squared_evens[4, 16, 36, 64, 100]}")4950# Dict comprehension51print("\nDict comprehension:")5253numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]5455# Create dict with computed values56squares_dict→ {1: 1, 2: 4, 3: 9, 4: 16} = {n: sq→ 25 for n in numbers[1, 2, 3, 4, 5] if (sq := n * n) < 20}57print(f"Squares dict: {squares_dict{1: 1, 2: 4, 3: 9, 4: 16}}")5859# Nested comprehension60print("\nNested comprehension:")6162matrix→ [[1, 2, 3], [4, 5, 6], [7, 8, 9]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]6364# Flatten and filter with transformation65result→ [10, 12, 14, 16, 18] = [doubled→ 18 for row in matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]] for item in row if (doubled := item * 2) > 8]66print(f"Filtered doubled: {result[10, 12, 14, 16, 18]}")6768# Generator expression69print("\nGenerator expression:")7071numbers→ range(1, 11) = range(1, 11)7273# Generator with walrus74gen→ <generator object <genexpr> at ⟨addr A⟩> = (sq25 for n in numbersrange(1, 11) if (sq := n * n) > 20)75result→ [25, 36, 49, 64, 81, 100] = list(gen<generator object <genexpr> at ⟨addr A⟩>)76print(f"Squares > 20: {result[25, 36, 49, 64, 81, 100]}")7778# Any/All with walrus79print("\nAny/All with walrus:")8081data→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]outputResult walrus (called once): [30, 40, 50] String processing: Long words (uppercase): ['PYTHON', 'PROGRAMMING'] Data transformation: Even squares: [4, 16, 36, 64, 100] Dict comprehension: Squares dict: {1: 1, 2: 4, 3: 9, 4: 16} Nested comprehension: Filtered doubled: [10, 12, 14, 16, 18] Generator expression: Squares > 20: [25, 36, 49, 64, 81, 100] Any/All with walrus:if any((sq := n * n) > 20 for n in data):
83# Check if any squared value > 2084if any((sq25 := n * n) > 20 for n in data[1, 2, 3, 4, 5]):85 print(f"Found square > 20")outputFound square > 20numbers ← [1, 2, 3, 4, 5, 6, 7], first_big ← 25, words ← ['hello', 'world', 'hello', 'python', 'world']
87# Get first match with walrus88numbers→ [1, 2, 3, 4, 5, 6, 7] = [1, 2, 3, 4, 5, 6, 7]89first_big→ 25 = next((sq25 for n in numbers[1, 2, 3, 4, 5, 6, 7] if (sq := n * n) > 20), None)90print(f"First square > 20: {first_big25}")9192# Set comprehension93print("\nSet comprehension:")9495words→ ['hello', 'world', 'hello', 'python', 'world'] = ["hello", "world", "hello", "python", "world"]9697# Get unique lengths98lengths→ {5, 6} = {ln→ 5 for word in words['hello', 'world', 'hello', 'python', 'world'] if (ln := len(word)) > 4}99print(f"Unique lengths > 4: {lengths{5, 6}}")100101# Multiple conditions102print("\nMultiple conditions:")103104numbers→ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]105106# Multiple transformations107result→ [6, 8, 10, 12, 14] = [108 doubled→ 20 109 for n in numbers[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 110 if (doubled→ 20 := n * 2) > 5 111 if (squared→ 400 := doubled→ 20 * doubled) < 200112]113print(f"Filtered transformations: {result[6, 8, 10, 12, 14]}")114115# Practical example116print("\nPractical example:")117118# Process user data119users→ [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}] = [120 {"name": "Alice", "age": 30},121 {"name": "Bob", "age": 25},122 {"name": "Charlie", "age": 35}123]124125# Get names of users over 26126names→ ['Alice', 'Charlie'] = [name→ Charlie for user in users[{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}] if (age→ 35 := user.get("age", 0)) > 26 and (name := user.get("name"))]127print(f"Users over 26: {names['Alice', 'Charlie']}")128129# Parse and validate130raw_data→ ['10', '20', 'abc', '30', 'def'] = ["10", "20", "abc", "30", "def"]131132def try_parse(s):133 try:134 return int(s)135 except ValueError:136 return None137138# Get valid integers > 15139valid = [num(empty) for s in raw_data['10', '20', 'abc', '30', 'def'] if (num := try_parse(s)) is not None and num > 15]140print(f"Valid numbers > 15: {valid}")outputFirst square > 20: 25 Set comprehension: Unique lengths > 4: {5, 6} Multiple conditions: Filtered transformations: [6, 8, 10, 12, 14] Practical example: Users over 26: ['Alice', 'Charlie']def try_parse(s):
pass 1 of 5132def try_parse(s10):133 try:134 return int(s)All 5 passes — pass 1 is the card above pass s1 10 2 20 3 abc 4 30 5 def try:
pass 1 of 5132def try_parse(s):133 try:134 return int(s10)135 except ValueError:All 5 passes — pass 1 is the card above pass s1 10 2 20 3 abc 4 30 5 def num ← None, valid ← [20, 30], lines ← ['# comment', 'data: 10', '# ignore', 'data: 20', 'data: 30']
138# Get valid integers > 15139valid→ [20, 30] = [num→ None for s in raw_data['10', '20', 'abc', '30', 'def'] if (num := try_parse(s)) is not None and num > 15]140print(f"Valid numbers > 15: {valid[20, 30]}")141142# File processing simulation143lines→ ['# comment', 'data: 10', '# ignore', 'data: 20', 'data: 30'] = ["# comment", "data: 10", "# ignore", "data: 20", "data: 30"]144145# Extract data lines and parse146data_values→ [10, 20, 30] = [147 int(parts[1]→ 30)148 for line in lines['# comment', 'data: 10', '# ignore', 'data: 20', 'data: 30']149 if not line.startswith("#")150 if (parts→ ['data', '30'] := line.split(": "))151 if len(parts→ ['data', '30']) == 2152]153print(f"Data values: {data_values[10, 20, 30]}")outputValid numbers > 15: [20, 30] Data values: [10, 20, 30]
This is particularly valuable when the computation is expensive or has side effects you want to minimize.
Avoiding Repeated Calls
"""Walrus operator to avoid repeated calls"""
# Avoiding double computation
print("Avoiding double computation:")
def expensive_function(x):
print(f" Computing for {x}...")
return x ** 3
# Without walrus - calls function twice
x = 5
if expensive_function(x) > 100:
result = expensive_function(x)
print(f"Result: {result}")
# With walrus - calls once
x = 5
if (result := expensive_function(x)) > 100:
print(f"Result (walrus): {result}")
# Method calls
print("\nMethod calls:")
text = " Hello World "
# Without walrus - strip called twice
if len(text.strip()) > 5:
cleaned = text.strip()
print(f"Cleaned: '{cleaned}'")
# With walrus - strip called once
if len(cleaned := text.strip()) > 5:
print(f"Cleaned (walrus): '{cleaned}'")
# Regex matching
print("\nRegex matching:")
import re
text = "Error: File not found"
# Without walrus - match called twice
pattern = r"Error: (.*)"
if re.match(pattern, text):
match = re.match(pattern, text)
print(f"Error message: {match.group(1)}")
# With walrus - match called once
if (match := re.match(pattern, text)):
print(f"Error message (walrus): {match.group(1)}")
# Database query
print("\nDatabase query:")
def find_user(user_id):
print(f" Querying database for user {user_id}...")
users = {1: {"name": "Alice", "email": "alice@example.com"}}
return users.get(user_id)
# Without walrus - queries twice
user_id = 1
if find_user(user_id):
user = find_user(user_id)
print(f"User: {user}")
# With walrus - queries once
if (user := find_user(user_id)):
print(f"User (walrus): {user}")
# List operations
print("\nList operations:")
numbers = [1, 2, 3, 4, 5]
# Without walrus - sum called multiple times
if sum(numbers) > 10:
total = sum(numbers)
avg = total / len(numbers)
print(f"Average: {avg}")
# With walrus - sum called once
if (total := sum(numbers)) > 10:
avg = total / len(numbers)
print(f"Average (walrus): {avg}")
# File operations
print("\nFile operations:")
def read_config():
print(" Reading config file...")
return {"debug": True, "port": 8080, "host": "localhost"}
# Without walrus - reads twice
if "debug" in read_config():
config = read_config()
print(f"Debug enabled on {config['host']}:{config['port']}")
# With walrus - reads once
if (config := read_config()) and "debug" in config:
print(f"Debug enabled (walrus) on {config['host']}:{config['port']}")
# JSON parsing
print("\nJSON parsing:")
import json
def parse_json(json_str):
print(f" Parsing JSON...")
try:
return json.loads(json_str)
except:
return None
json_str = '{"name": "Alice", "age": 30}'
# Without walrus - parses twice
if parse_json(json_str):
data = parse_json(json_str)
print(f"Name: {data.get('name')}")
# With walrus - parses once
if (data := parse_json(json_str)):
print(f"Name (walrus): {data.get('name')}")
# API calls
print("\nAPI calls:")
def fetch_data(endpoint):
print(f" Fetching from {endpoint}...")
return {"status": 200, "data": [1, 2, 3, 4, 5]}
# Without walrus - fetches twice
endpoint = "/api/users"
if fetch_data(endpoint).get("status") == 200:
response = fetch_data(endpoint)
print(f"Data: {response.get('data')}")
# With walrus - fetches once
if (response := fetch_data(endpoint)).get("status") == 200:
print(f"Data (walrus): {response.get('data')}")
# Validation chains
print("\nValidation chains:")
def validate_input(value):
print(f" Validating {value}...")
return value if value and len(value) >= 3 else None
user_input = "alice"
# Without walrus - validates multiple times
if validate_input(user_input):
validated = validate_input(user_input)
if len(validated) <= 10:
final = validated.upper()
print(f"Valid: {final}")
# With walrus - validates once
if (validated := validate_input(user_input)) and len(validated) <= 10:
final = validated.upper()
print(f"Valid (walrus): {final}")
# Practical example
print("\nPractical example:")
# Cache lookup
cache = {1: "cached_value_1"}
def compute_expensive(key):
print(f" Computing for key {key}...")
return f"computed_value_{key}"
def get_or_compute(key):
# Without walrus
if key in cache:
return cache[key]
else:
result = compute_expensive(key)
cache[key] = result
return result
# With walrus - cleaner
def get_or_compute_walrus(key):
if (result := cache.get(key)) is not None:
return result
cache[key] = (result := compute_expensive(key))
return result
print(f"Get 1: {get_or_compute_walrus(1)}") # From cache
print(f"Get 2: {get_or_compute_walrus(2)}") # Computed
# Form validation
def validate_email(email):
print(f" Validating email: {email}")
return "@" in email and "." in email
def validate_age(age):
print(f" Validating age: {age}")
return 0 < age < 150
email = "alice@example.com"
age = 30
# Without walrus - validates each twice
if validate_email(email) and validate_age(age):
email_valid = validate_email(email)
age_valid = validate_age(age)
print(f"Email: {email_valid}, Age: {age_valid}")
# With walrus - validates once each
if (email_valid := validate_email(email)) and (age_valid := validate_age(age)):
print(f"Email (walrus): {email_valid}, Age: {age_valid}")
x ← 5
1"""Walrus operator to avoid repeated calls"""23# Avoiding double computation4print("Avoiding double computation:")56def expensive_function(x):7 print(f" Computing for {x}...")8 return x ** 3910# Without walrus - calls function twice11x→ 5 = 512if expensive_function(x) > 100:outputAvoiding double computation:def expensive_function(x):
pass 1 of 36def expensive_function(x5):7 print(f" Computing for {x5}...")8 return x5 ** 3output Computing for 5...All 3 passes — pass 1 is the card above pass result1 — 2 — 3 125 if expensive_function(x) > 100:
11x = 512if expensive_function(x5) > 100:13 result = expensive_function(x5)14 print(f"Result: {result}")result ← 125
12if expensive_function(x) > 100:13 result→ 125 = expensive_function(x5)14 print(f"Result: {result125}")outputResult: 125x ← 5
16# With walrus - calls once17x→ 5 = 518if (result := expensive_function(x)) > 100:if (result := expensive_function(x)) > 100:
17x = 518if (result125 := expensive_function(x5)) > 100:19 print(f"Result (walrus): {result125}")outputResult (walrus): 125text ← Hello World
21# Method calls22print("\nMethod calls:")2324text→ Hello World = " Hello World "output Method calls:cleaned ← Hello World
26# Without walrus - strip called twice27if len(text Hello World .strip()) > 5:28 cleaned→ Hello World = text Hello World .strip()29 print(f"Cleaned: '{cleanedHello World}'")outputCleaned: 'Hello World'if len(cleaned := text.strip()) > 5:
31# With walrus - strip called once32if len(cleanedHello World := text Hello World .strip()) > 5:33 print(f"Cleaned (walrus): '{cleanedHello World}'")outputCleaned (walrus): 'Hello World'text ← Error: File not found, pattern ← Error: (.*)
35# Regex matching36print("\nRegex matching:")3738import re3940text→ Error: File not found = "Error: File not found"4142# Without walrus - match called twice43pattern→ Error: (.*) = r"Error: (.*)"44if re.match(pattern, text):output Regex matching:match ← <re.Match object; span=(0, 21), match='Error: File not found'>
43pattern = r"Error: (.*)"44if re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.match(patternError: (.*), textError: File not found):45 match→ <re.Match object; span=(0, 21), match='Error: File not found'> = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.match(patternError: (.*), textError: File not found)46 print(f"Error message: {match<re.Match object; span=(0, 21), match='Error: File not found'>.group(1)}")outputError message: File not foundif (match := re.match(pattern, text)):
48# With walrus - match called once49if (match<re.Match object; span=(0, 21), match='Error: File not found'> := re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.match(patternError: (.*), textError: File not found)):50 print(f"Error message (walrus): {match<re.Match object; span=(0, 21), match='Error: File not found'>.group(1)}")outputError message (walrus): File not founduser_id ← 1
52# Database query53print("\nDatabase query:")5455def find_user(user_id):56 print(f" Querying database for user {user_id}...")57 users = {1: {"name": "Alice", "email": "alice@example.com"}}58 return users.get(user_id)5960# Without walrus - queries twice61user_id→ 1 = 162if find_user(user_id):output Database query:users ← {1: {'name': 'Alice', 'email': 'alice@example.com'}}
pass 1 of 355def find_user(user_id1):56 print(f" Querying database for user {user_id1}...")57 users→ {1: {'name': 'Alice', 'email': 'alice@example.com'}} = {1: {"name": "Alice", "email": "alice@example.com"}}58 return users{1: {'name': 'Alice', 'email': 'alice@example.com'}}.get(user_id1)output Querying database for user 1...All 3 passes — pass 1 is the card above pass userusers1 — {1: {'name': 'Alice', 'email': 'alice@example.com'}} 2 — {1: {'name': 'Alice', 'email': 'alice@example.com'}} 3 {'name': 'Alice', 'email': 'alice@example.com'} {1: {'name': 'Alice', 'email': 'alice@example.com'}} if find_user(user_id):
61user_id = 162if find_user(user_id1):63 user = find_user(user_id1)64 print(f"User: {user}")user ← {'name': 'Alice', 'email': 'alice@example.com'}
62if find_user(user_id):63 user→ {'name': 'Alice', 'email': 'alice@example.com'} = find_user(user_id1)64 print(f"User: {user{'name': 'Alice', 'email': 'alice@example.com'}}")outputUser: {'name': 'Alice', 'email': 'alice@example.com'}if (user := find_user(user_id)):
66# With walrus - queries once67if (user{'name': 'Alice', 'email': 'alice@example.com'} := find_user(user_id1)):68 print(f"User (walrus): {user{'name': 'Alice', 'email': 'alice@example.com'}}")outputUser (walrus): {'name': 'Alice', 'email': 'alice@example.com'}numbers ← [1, 2, 3, 4, 5]
70# List operations71print("\nList operations:")7273numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]output List operations:total ← 15, avg ← 3.0
75# Without walrus - sum called multiple times76if sum(numbers[1, 2, 3, 4, 5]) > 10:77 total→ 15 = sum(numbers[1, 2, 3, 4, 5])78 avg→ 3.0 = total15 / len(numbers[1, 2, 3, 4, 5])79 print(f"Average: {avg3.0}")outputAverage: 3.0avg ← 3.0
81# With walrus - sum called once82if (total15 := sum(numbers[1, 2, 3, 4, 5])) > 10:83 avg→ 3.0 = total15 / len(numbers[1, 2, 3, 4, 5])84 print(f"Average (walrus): {avg3.0}")outputAverage (walrus): 3.0print(" File operations:")
86# File operations87print("\nFile operations:")output File operations:def read_config():
pass 1 of 389def read_config():90 print(" Reading config file...")91 return {"debug": True, "port": 8080, "host": "localhost"}output Reading config file...All 3 passes — pass 1 is the card above pass configconfig[’host’]config[’port’]1 — — — 2 — — — 3 {'debug': True, 'port': 8080, 'host': 'localhost'} localhost 8080 config ← {'debug': True, 'port': 8080, 'host': 'localhost'}
94if "debug" in read_config():95 config→ {'debug': True, 'port': 8080, 'host': 'localhost'} = read_config()96 print(f"Debug enabled on {config['host']localhost}:{config['port']8080}")outputDebug enabled on localhost:8080if (config := read_config()) and "debug" in config:
98# With walrus - reads once99if (config{'debug': True, 'port': 8080, 'host': 'localhost'} := read_config()) and "debug" in config:100 print(f"Debug enabled (walrus) on {config['host']localhost}:{config['port']8080}")outputDebug enabled (walrus) on localhost:8080json_str ← {"name": "Alice", "age": 30}
102# JSON parsing103print("\nJSON parsing:")104105import json106107def parse_json(json_str):108 print(f" Parsing JSON...")109 try:110 return json.loads(json_str)111 except:112 return None113114json_str→ {"name": "Alice", "age": 30} = '{"name": "Alice", "age": 30}'output JSON parsing:def parse_json(json_str):
pass 1 of 3107def parse_json(json_str{"name": "Alice", "age": 30}):108 print(f" Parsing JSON...")109 try:output Parsing JSON...All 3 passes — pass 1 is the card above pass data1 — 2 — 3 {'name': 'Alice', 'age': 30} try:
pass 1 of 3108print(f" Parsing JSON...")109try:110 return json<module 'json' from '/usr/local/lib/python3.12/json/__init__.py'>.loads(json_str{"name": "Alice", "age": 30})111except:All 3 passes — pass 1 is the card above pass data1 — 2 — 3 {'name': 'Alice', 'age': 30} if parse_json(json_str):
116# Without walrus - parses twice117if parse_json(json_str{"name": "Alice", "age": 30}):118 data = parse_json(json_str{"name": "Alice", "age": 30})119 print(f"Name: {data.get('name')}")data ← {'name': 'Alice', 'age': 30}
117if parse_json(json_str):118 data→ {'name': 'Alice', 'age': 30} = parse_json(json_str{"name": "Alice", "age": 30})119 print(f"Name: {data{'name': 'Alice', 'age': 30}.get('name')}")outputName: Aliceif (data := parse_json(json_str)):
121# With walrus - parses once122if (data{'name': 'Alice', 'age': 30} := parse_json(json_str{"name": "Alice", "age": 30})):123 print(f"Name (walrus): {data{'name': 'Alice', 'age': 30}.get('name')}")outputName (walrus): Aliceendpoint ← /api/users
125# API calls126print("\nAPI calls:")127128def fetch_data(endpoint):129 print(f" Fetching from {endpoint}...")130 return {"status": 200, "data": [1, 2, 3, 4, 5]}131132# Without walrus - fetches twice133endpoint→ /api/users = "/api/users"134if fetch_data(endpoint).get("status") == 200:output API calls:def fetch_data(endpoint):
pass 1 of 3128def fetch_data(endpoint/api/users):129 print(f" Fetching from {endpoint/api/users}...")130 return {"status": 200, "data": [1, 2, 3, 4, 5]}output Fetching from /api/users...All 3 passes — pass 1 is the card above pass response1 — 2 — 3 {'status': 200, 'data': [1, 2, 3, 4, 5]} if fetch_data(endpoint).get("status") == 200:
133endpoint = "/api/users"134if fetch_data(endpoint/api/users).get("status") == 200:135 response = fetch_data(endpoint/api/users)136 print(f"Data: {response.get('data')}")response ← {'status': 200, 'data': [1, 2, 3, 4, 5]}
134if fetch_data(endpoint).get("status") == 200:135 response→ {'status': 200, 'data': [1, 2, 3, 4, 5]} = fetch_data(endpoint/api/users)136 print(f"Data: {response{'status': 200, 'data': [1, 2, 3, 4, 5]}.get('data')}")outputData: [1, 2, 3, 4, 5]if (response := fetch_data(endpoint)).get("status") == 200:
138# With walrus - fetches once139if (response{'status': 200, 'data': [1, 2, 3, 4, 5]} := fetch_data(endpoint/api/users)).get("status") == 200:140 print(f"Data (walrus): {response{'status': 200, 'data': [1, 2, 3, 4, 5]}.get('data')}")outputData (walrus): [1, 2, 3, 4, 5]user_input ← alice
142# Validation chains143print("\nValidation chains:")144145def validate_input(value):146 print(f" Validating {value}...")147 return value if value and len(value) >= 3 else None148149user_input→ alice = "alice"output Validation chains:def validate_input(value):
pass 1 of 3145def validate_input(valuealice):146 print(f" Validating {valuealice}...")147 return valuealice if value and len(value) >= 3 else Noneoutput Validating alice...All 3 passes — pass 1 is the card above pass user_inputvalidatedfinal1 alice — — 2 — — — 3 alice alice ALICE if validate_input(user_input):
151# Without walrus - validates multiple times152if validate_input(user_inputalice):153 validated = validate_input(user_inputalice)154 if len(validated) <= 10:validated ← alice
152if validate_input(user_input):153 validated→ alice = validate_input(user_inputalice)154 if len(validated) <= 10:final ← ALICE
153validated = validate_input(user_input)154if len(validatedalice) <= 10:155 final→ ALICE = validatedalice.upper()156 print(f"Valid: {finalALICE}")outputValid: ALICEfinal ← ALICE
158# With walrus - validates once159if (validatedalice := validate_input(user_inputalice)) and len(validated) <= 10:160 final→ ALICE = validatedalice.upper()161 print(f"Valid (walrus): {finalALICE}")outputValid (walrus): ALICEcache ← {1: 'cached_value_1'}
163# Practical example164print("\nPractical example:")165166# Cache lookup167cache→ {1: 'cached_value_1'} = {1: "cached_value_1"}168169def compute_expensive(key):170 print(f" Computing for key {key}...")171 return f"computed_value_{key}"172173def get_or_compute(key):174 # Without walrus175 if key in cache:176 return cache[key]177 else:178 result = compute_expensive(key)179 cache[key] = result180 return result181182# With walrus - cleaner183def get_or_compute_walrus(key):184 if (result := cache.get(key)) is not None:185 return result186 cache[key] = (result := compute_expensive(key))187 return result188189print(f"Get 1: {get_or_compute_walrus(1)}") # From cache190print(f"Get 2: {get_or_compute_walrus(2)}") # Computedoutput Practical example:def get_or_compute_walrus(key):
pass 1 of 2182# With walrus - cleaner183def get_or_compute_walrus(key1):184 if (result := cache.get(key)) is not None:185 return resultif (result := cache.get(key)) is not None:
183def get_or_compute_walrus(key):184 if (resultcached_value_1 := cache{1: 'cached_value_1'}.get(key1)) is not None:185 return resultcached_value_1186 cache[key] = (result := compute_expensive(key))print(f"Get 1: {get_or_compute_walrus(1)}") # From cache
189print(f"Get 1: {get_or_compute_walrus(1)}") # From cache190print(f"Get 2: {get_or_compute_walrus(2)}") # ComputedoutputGet 1: cached_value_1def get_or_compute_walrus(key):
pass 2 of 2182# With walrus - cleaner183def get_or_compute_walrus(key2):184 if (result := cache.get(key)) is not None:185 return result186 cache[key] = (resultNone := compute_expensive(key2))187 return resultdef compute_expensive(key):
169def compute_expensive(key2):170 print(f" Computing for key {key2}...")171 return f"computed_value_{key2}"output Computing for key 2...result ← computed_value_2, cache[key] ← computed_value_2
185 return result186cache[key]→ computed_value_2 = (result→ computed_value_2 := compute_expensive(key2))187return resultcomputed_value_2email ← alice@example.com, age ← 30
189print(f"Get 1: {get_or_compute_walrus(1)}") # From cache190print(f"Get 2: {get_or_compute_walrus(2)}") # Computed191192# Form validation193def validate_email(email):194 print(f" Validating email: {email}")195 return "@" in email and "." in email196197def validate_age(age):198 print(f" Validating age: {age}")199 return 0 < age < 150200201email→ alice@example.com = "alice@example.com"202age→ 30 = 30outputGet 2: computed_value_2def validate_email(email):
pass 1 of 3192# Form validation193def validate_email(emailalice@example.com):194 print(f" Validating email: {emailalice@example.com}")195 return "@" in emailalice@example.com and "." in emailoutput Validating email: alice@example.comAll 3 passes — pass 1 is the card above pass ageemail_validage_valid1 30 — — 2 — — — 3 30 True True def validate_age(age):
pass 1 of 3197def validate_age(age30):198 print(f" Validating age: {age30}")199 return 0 < age30 < 150output Validating age: 30All 3 passes — pass 1 is the card above pass emailemail_validage_valid1 alice@example.com — — 2 — — — 3 alice@example.com True True if validate_email(email) and validate_age(age):
204# Without walrus - validates each twice205if validate_email(emailalice@example.com) and validate_age(age30):206 email_valid = validate_email(emailalice@example.com)207 age_valid = validate_age(age)email_valid ← True
205if validate_email(email) and validate_age(age):206 email_valid→ True = validate_email(emailalice@example.com)207 age_valid = validate_age(age30)208 print(f"Email: {email_valid}, Age: {age_valid}")age_valid ← True
206email_valid = validate_email(email)207age_valid→ True = validate_age(age30)208print(f"Email: {email_validTrue}, Age: {age_validTrue}")outputEmail: True, Age: Trueif (email_valid := validate_email(email)) and (age_valid := validate_a…
210# With walrus - validates once each211if (email_validTrue := validate_email(emailalice@example.com)) and (age_validTrue := validate_age(age30)):212 print(f"Email (walrus): {email_validTrue}, Age: {age_validTrue}")outputEmail (walrus): True, Age: True
Any time you find yourself calling the same function twice to check and use a result, consider the walrus operator.
When Not to Use
"""When not to use walrus operator"""
# Reduces readability
print("Reduces readability:")
# Bad - too complex
numbers = [1, 2, 3, 4, 5]
result = [y for x in numbers if (y := x * 2) > 5 if (z := y + 1) < 15]
print(f"Complex walrus: {result}")
# Better - split into steps
doubled = [x * 2 for x in numbers]
filtered = [y for y in doubled if y > 5 and y + 1 < 15]
print(f"Clear steps: {filtered}")
# Unnecessary complexity
print("\nUnnecessary complexity:")
# Bad - walrus adds no value
if (x := 5) == 5:
print(f"x is {x}")
# Better - simple assignment
x = 5
if x == 5:
print(f"x is {x}")
# Simple assignments
print("\nSimple assignments:")
# Bad - walrus not needed
data = [1, 2, 3]
if (length := len(data)) > 0:
print(f"Has {length} items")
# Better - separate lines when not reusing
if len(data) > 0:
print(f"Has {len(data)} items")
# Good use - value reused
if (length := len(data)) > 0:
average = sum(data) / length
print(f"Average of {length} items: {average}")
# Mutation confusion
print("\nMutation confusion:")
# Bad - unclear what's being assigned
items = [1, 2, 3]
if (items := items + [4]) and len(items) > 3:
print(f"Items: {items}")
# Better - explicit mutation
items = [1, 2, 3]
items = items + [4]
if len(items) > 3:
print(f"Items: {items}")
# Debugging difficulty
print("\nDebugging difficulty:")
# Bad - hard to debug
def process(x):
return x * 2
numbers = [1, 2, 3, 4, 5]
if any((result := process(n)) > 5 for n in numbers):
print(f"Found: {result}") # Which result?
# Better - explicit loop
for n in numbers:
result = process(n)
if result > 5:
print(f"Found: {result}")
break
# Scope confusion
print("\nScope confusion:")
# Bad - walrus creates variable in outer scope
data = [1, 2, 3, 4, 5]
evens = [x for x in data if (is_even := x % 2 == 0)]
print(f"Last is_even value: {is_even}") # Unexpected side effect
# Better - keep scope clear
evens = [x for x in data if x % 2 == 0]
print(f"Evens: {evens}")
# Multiple assignments
print("\nMultiple assignments:")
# Bad - trying to assign multiple values
try:
if (a := 1, b := 2): # Syntax error
pass
except SyntaxError:
print("Cannot use multiple := in one expression")
# Better - separate assignments
a, b = 1, 2
if a and b:
print(f"a={a}, b={b}")
# Class attributes
print("\nClass attributes:")
# Bad - walrus in class definition
class BadExample:
# This doesn't work as expected
# value = (cached := compute())
pass
# Better - regular assignment
class GoodExample:
def __init__(self):
self.value = self.compute()
def compute(self):
return 42
obj = GoodExample()
print(f"Value: {obj.value}")
# Performance misconception
print("\nPerformance misconception:")
# Bad - thinking walrus improves performance
numbers = list(range(50))
# Walrus doesn't make this faster
total = sum(n for n in numbers if (doubled := n * 2) > 500)
# Better - same speed, clearer
total = sum(n * 2 for n in numbers if n * 2 > 500)
print(f"Total: {total}")
# When walrus is good
print("\nWhen walrus is good:")
# Good: Avoid repeated expensive calls
def expensive():
return 42
if (result := expensive()) > 40:
print(f"Good use: {result}")
# Good: Capture match object
import re
text = "Error: Something failed"
if (match := re.search(r"Error: (.*)", text)):
print(f"Good use: {match.group(1)}")
# Good: Read lines
lines = iter(["line 1", "line 2", ""])
while (line := next(lines, None)) and line:
print(f"Good use: {line}")
# Best practices
print("\nBest practices:")
# DO use walrus when:
# 1. Avoiding repeated expensive calls
def fetch_data():
return {"value": 100}
if (data := fetch_data()).get("value", 0) > 50:
print(f"✓ Data: {data}")
# 2. Capturing intermediate values in comprehensions
numbers = [1, 2, 3, 4, 5]
squares = [sq for n in numbers if (sq := n * n) > 10]
print(f"✓ Squares: {squares}")
# DON'T use walrus when:
# 1. Simple assignments suffice
x = 10 # Not: if (x := 10)
print(f"✓ Simple: {x}")
# 2. Reduces readability
# Not: if (a := b := c := 1)
a = b = c = 1
print(f"✓ Clear: a={a}")
# 3. In complex nested expressions
# Keep it simple!
numbers ← [1, 2, 3, 4, 5], y ← 10, z ← 11, result ← [6, 8, 10]
1"""When not to use walrus operator"""23# Reduces readability4print("Reduces readability:")56# Bad - too complex7numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]8result→ [6, 8, 10] = [y→ 10 for x in numbers[1, 2, 3, 4, 5] if (y := x * 2) > 5 if (z→ 11 := y + 1) < 15]9print(f"Complex walrus: {result[6, 8, 10]}")1011# Better - split into steps12doubled→ [2, 4, 6, 8, 10] = [x * 2 for x in numbers[1, 2, 3, 4, 5]]13filtered→ [6, 8, 10] = [y for y in doubled[2, 4, 6, 8, 10] if y > 5 and y + 1 < 15]14print(f"Clear steps: {filtered[6, 8, 10]}")1516# Unnecessary complexity17print("\nUnnecessary complexity:")outputReduces readability: Complex walrus: [6, 8, 10] Clear steps: [6, 8, 10] Unnecessary complexity:if (x := 5) == 5:
19# Bad - walrus adds no value20if (x5 := 5) == 5:21 print(f"x is {x5}")outputx is 5x ← 5
23# Better - simple assignment24x→ 5 = 525if x == 5:if x == 5:
24x = 525if x5 == 5:26 print(f"x is {x5}")outputx is 5data ← [1, 2, 3]
28# Simple assignments29print("\nSimple assignments:")3031# Bad - walrus not needed32data→ [1, 2, 3] = [1, 2, 3]33if (length := len(data)) > 0:output Simple assignments:if (length := len(data)) > 0:
32data = [1, 2, 3]33if (length3 := len(data[1, 2, 3])) > 0:34 print(f"Has {length3} items")outputHas 3 itemsif len(data) > 0:
36# Better - separate lines when not reusing37if len(data[1, 2, 3]) > 0:38 print(f"Has {len(data[1, 2, 3])} items")outputHas 3 itemsaverage ← 2.0
40# Good use - value reused41if (length3 := len(data[1, 2, 3])) > 0:42 average→ 2.0 = sum(data[1, 2, 3]) / length343 print(f"Average of {length3} items: {average2.0}")outputAverage of 3 items: 2.0items ← [1, 2, 3]
45# Mutation confusion46print("\nMutation confusion:")4748# Bad - unclear what's being assigned49items→ [1, 2, 3] = [1, 2, 3]50if (items := items + [4]) and len(items) > 3:output Mutation confusion:if (items := items + [4]) and len(items) > 3:
49items = [1, 2, 3]50if (items[1, 2, 3, 4] := items + [4]) and len(items) > 3:51 print(f"Items: {items[1, 2, 3, 4]}")outputItems: [1, 2, 3, 4]items ← [1, 2, 3]
53# Better - explicit mutation54items→ [1, 2, 3] = [1, 2, 3]55items→ [1, 2, 3, 4] = items + [4]56if len(items) > 3:if len(items) > 3:
55items = items + [4]56if len(items[1, 2, 3, 4]) > 3:57 print(f"Items: {items[1, 2, 3, 4]}")outputItems: [1, 2, 3, 4]numbers ← [1, 2, 3, 4, 5]
59# Debugging difficulty60print("\nDebugging difficulty:")6162# Bad - hard to debug63def process(x):64 return x * 26566numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]67if any((result := process(n)) > 5 for n in numbers):output Debugging difficulty:def process(x):
pass 1 of 662# Bad - hard to debug63def process(x1):64 return x1 * 2All 6 passes — pass 1 is the card above pass xresultnumbers1 1 — — 2 2 — — 3 3 6 [1, 2, 3, 4, 5] 4 1 — — 5 2 — — 6 3 — — if any((result := process(n)) > 5 for n in numbers):
66numbers = [1, 2, 3, 4, 5]67if any((result6 := process(n)) > 5 for n in numbers[1, 2, 3, 4, 5]):68 print(f"Found: {result6}") # Which result?outputFound: 6for n in numbers:
pass 1 of 370# Better - explicit loop71for n1 in numbers[1, 2, 3, 4, 5]:72 result = process(n1)73 if result > 5:All 3 passes — pass 1 is the card above pass n1 1 2 2 3 3 result ← 2
71for n in numbers:72 result→ 2 = process(n1)73 if result > 5:result ← 4
71for n in numbers:72 result→ 4 = process(n2)73 if result > 5:result ← 6
71for n in numbers:72 result→ 6 = process(n3)73 if result > 5:if result > 5:
72result = process(n)73if result6 > 5:74 print(f"Found: {result6}")75 breakoutputFound: 6data ← [1, 2, 3, 4, 5], is_even ← False, evens ← [2, 4]
77# Scope confusion78print("\nScope confusion:")7980# Bad - walrus creates variable in outer scope81data→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]82evens→ [2, 4] = [x for x in data[1, 2, 3, 4, 5] if (is_even→ False := x % 2 == 0)]83print(f"Last is_even value: {is_evenFalse}") # Unexpected side effect8485# Better - keep scope clear86evens→ [2, 4] = [x for x in data[1, 2, 3, 4, 5] if x % 2 == 0]87print(f"Evens: {evens[2, 4]}")8889# Multiple assignments90print("\nMultiple assignments:")output Scope confusion: Last is_even value: False Evens: [2, 4] Multiple assignments:if (a := 1, b := 2): # Syntax error
93try:94 if (a1 := 1, b2 := 2): # Syntax error95 pass96except SyntaxError:a ← 1, b ← 2
99# Better - separate assignments100a→ 1, b→ 2 = 1, 2101if a and b:if a and b:
100a, b = 1, 2101if a1 and b2:102 print(f"a={a1}, b={b2}")outputa=1, b=2print(" Class attributes:")
104# Class attributes105print("\nClass attributes:")106107# Bad - walrus in class definition108class BadExample:109 # This doesn't work as expected110 # value = (cached := compute())111 pass112113# Better - regular assignment114class GoodExample:115 def __init__(self):116 self.value = self.compute()117 118 def compute(self):119 return 42120121obj = GoodExample()122print(f"Value: {obj.value}")output Class attributes:def __init__(self):
114class GoodExample:115 def __init__(self⟨GoodExample A⟩):116 self.value = self⟨GoodExample A⟩.compute()def compute(self):
118def compute(self⟨GoodExample A⟩):119 return 42self.value ← 42, obj ← ⟨GoodExample A⟩, numbers ← [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
115 def __init__(self):116 self.value→ 42 = self⟨GoodExample A⟩.compute()117 118 def compute(self):119 return 42120121obj→ ⟨GoodExample A⟩ = GoodExample()122print(f"Value: {obj.value42}")123124# Performance misconception125print("\nPerformance misconception:")126127# Bad - thinking walrus improves performance128numbers→ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] = list(range(50))129# Walrus doesn't make this faster130total→ 0 = sum(n for n in numbers[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] if (doubled→ 98 := n * 2) > 500)131132# Better - same speed, clearer133total→ 0 = sum(n * 2 for n in numbers[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] if n * 2 > 500)134print(f"Total: {total0}")135136# When walrus is good137print("\nWhen walrus is good:")outputValue: 42 Performance misconception: Total: 0 When walrus is good:if (result := expensive()) > 40:
143if (result42 := expensive()) > 40:144 print(f"Good use: {result42}")outputGood use: 42text ← Error: Something failed
147import re148text→ Error: Something failed = "Error: Something failed"149if (match := re.search(r"Error: (.*)", text)):if (match := re.search(r"Error: (.*)", text)):
148text = "Error: Something failed"149if (match<re.Match object; span=(0, 23), match='Error: Something failed'> := re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.search(r"Error: (.*)", textError: Something failed)):150 print(f"Good use: {match<re.Match object; span=(0, 23), match='Error: Something failed'>.group(1)}")outputGood use: Something failedlines ← ⟨list_iterator B⟩
152# Good: Read lines153lines→ ⟨list_iterator B⟩ = iter(["line 1", "line 2", ""])154while (line := next(lines, None)) and line:while (line := next(lines, None)) and line:
pass 1 of 2153lines = iter(["line 1", "line 2", ""])154while (lineline 1 := next(lines⟨list_iterator B⟩, None)) and line:155 print(f"Good use: {lineline 1}")outputGood use: line 1while (line := next(lines, None)) and line:
pass 2 of 2153lines = iter(["line 1", "line 2", ""])154while (lineline 2 := next(lines⟨list_iterator B⟩, None)) and line:155 print(f"Good use: {lineline 2}")outputGood use: line 2print(" Best practices:")
157# Best practices158print("\nBest practices:")output Best practices:if (data := fetch_data()).get("value", 0) > 50:
165if (data{'value': 100} := fetch_data()).get("value", 0) > 50:166 print(f"✓ Data: {data{'value': 100}}")output✓ Data: {'value': 100}numbers ← [1, 2, 3, 4, 5], sq ← 25, squares ← [16, 25], x ← 10
168# 2. Capturing intermediate values in comprehensions169numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]170squares→ [16, 25] = [sq→ 25 for n in numbers[1, 2, 3, 4, 5] if (sq := n * n) > 10]171print(f"✓ Squares: {squares[16, 25]}")172173# DON'T use walrus when:174# 1. Simple assignments suffice175x→ 10 = 10 # Not: if (x := 10)176print(f"✓ Simple: {x10}")177178# 2. Reduces readability179# Not: if (a := b := c := 1)180a→ 1 = b→ 1 = c→ 1 = 1181print(f"✓ Clear: a={a1}")output✓ Squares: [16, 25] ✓ Simple: 10 ✓ Clear: a=1
The walrus operator is a tool for specific situations. Overusing it makes code harder to read and debug.
Use Cases
- Avoid repeated function calls in conditions
- Capture values in comprehensions
- Simplify file and stream reading loops
- Debug intermediate values
- Reduce temporary variable clutter
Exercise: walrus_practice.py
Refactor a function that calls len() twice (once for check, once for use) to use the walrus operator