Skip to content

Commit 4fd45d0

Browse files
committed
Refactor top outlier lessons to shorten main
- arg_enforcement: promote distance and create_user to module level; add assert_raises_type_error helper - walrus_operator: introduce InputBuffer class and comprehension helpers demonstrating practical := usage - pattern_matching: group 68 assertions into structured verification functions with takeaways
1 parent 414bdb9 commit 4fd45d0

3 files changed

Lines changed: 154 additions & 204 deletions

File tree

‎ultimatepython/advanced/arg_enforcement.py‎

Lines changed: 65 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
These features give you fine-grained control over your function signatures.
1010
"""
1111

12+
from collections.abc import Callable
13+
from typing import Any
14+
1215

1316
def traditional_function(a: int, b: int, c: int) -> int:
1417
"""A traditional function where all parameters can be passed either way.
@@ -84,158 +87,87 @@ def complex_signature(a: int, b: int, /, c: int, d: int = 10, *, e: int, f: int
8487
return a + b + c + d + e + f
8588

8689

87-
def main() -> None:
88-
# Traditional function: can be called either way
89-
assert traditional_function(1, 2, 3) == 6
90-
assert traditional_function(a=1, b=2, c=3) == 6
91-
assert traditional_function(1, b=2, c=3) == 6
90+
def distance(x1: float, y1: float, x2: float, y2: float, /) -> float:
91+
"""Calculate distance between two points.
9292
93-
# Positional-only function: must use positional arguments
94-
assert positional_only(5, 3) == 8
95-
96-
# Trying to use keyword arguments with positional-only parameters
97-
# will raise a TypeError
98-
positional_error = False
99-
try:
100-
# This will fail because 'a' and 'b' are positional-only
101-
positional_only(a=5, b=3) # type: ignore [call-arg]
102-
except TypeError:
103-
positional_error = True
104-
assert positional_error is True
105-
106-
# You also can't mix positional and keyword for positional-only params
107-
positional_error2 = False
108-
try:
109-
# This will fail because 'b' is positional-only
110-
positional_only(5, b=3) # type: ignore [call-arg]
111-
except TypeError:
112-
positional_error2 = True
113-
assert positional_error2 is True
93+
The parameter names here are somewhat arbitrary (could be p1_x, etc.)
94+
so we make them positional-only to give us flexibility to rename them
95+
without breaking existing code.
96+
"""
97+
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
11498

115-
# Keyword-only function: must use keyword arguments
116-
assert keyword_only(x=4, y=5) == 20
11799

118-
# Trying to use positional arguments with keyword-only parameters
119-
# will raise a TypeError
120-
keyword_error = False
121-
try:
122-
# This will fail because 'x' and 'y' are keyword-only
123-
keyword_only(4, 5) # type: ignore [misc]
124-
except TypeError:
125-
keyword_error = True
126-
assert keyword_error is True
100+
def create_user(username: str, *, admin: bool = False, active: bool = True, send_email: bool = False) -> dict[str, object]:
101+
"""Create a user with clear intent for optional parameters.
127102
128-
# Mixed parameters demonstrate all three types
129-
result = mixed_parameters("first", "second", kw_only="third")
130-
assert result == "first-second-third"
103+
Making admin, active, and send_email keyword-only ensures that
104+
callers must specify exactly what they're setting, improving
105+
readability and preventing accidental mistakes.
106+
"""
107+
return {"username": username, "admin": admin, "active": active, "send_email": send_email}
131108

132-
# The middle parameter can be passed either way
133-
result2 = mixed_parameters("first", pos_or_kw="second", kw_only="third")
134-
assert result2 == "first-second-third"
135109

136-
# But positional-only must be positional
137-
mixed_error = False
110+
def assert_raises_type_error(fn: Callable[..., Any], *args: Any, **kwargs: Any) -> None:
111+
"""Verify that calling fn with given arguments raises a TypeError."""
112+
raised = False
138113
try:
139-
mixed_parameters(pos_only="first", pos_or_kw="second", kw_only="third") # type: ignore [call-arg]
114+
fn(*args, **kwargs)
140115
except TypeError:
141-
mixed_error = True
142-
assert mixed_error is True
116+
raised = True
117+
assert raised is True
143118

144-
# And keyword-only must be keyword
145-
mixed_error2 = False
146-
try:
147-
mixed_parameters("first", "second", "third") # type: ignore [misc]
148-
except TypeError:
149-
mixed_error2 = True
150-
assert mixed_error2 is True
151119

152-
# Positional-only with defaults
153-
assert positional_with_defaults(5) == 15 # Uses default b=10
154-
assert positional_with_defaults(5, 20) == 25 # Overrides b with 20
120+
def main() -> None:
121+
# Traditional function: can be called either way
122+
assert traditional_function(1, 2, 3) == 6
123+
assert traditional_function(a=1, b=2, c=3) == 6
124+
assert traditional_function(1, b=2, c=3) == 6
155125

156-
# Even with defaults, must use positional syntax
157-
positional_default_error = False
158-
try:
159-
positional_with_defaults(a=5, b=20) # type: ignore [call-arg]
160-
except TypeError:
161-
positional_default_error = True
162-
assert positional_default_error is True
126+
# Positional-only function: must use positional arguments
127+
assert positional_only(5, 3) == 8
128+
# Arguments before / cannot be passed by keyword name
129+
assert_raises_type_error(positional_only, a=5, b=3)
130+
assert_raises_type_error(positional_only, 5, b=3)
163131

164-
# Keyword-only with defaults
165-
assert keyword_with_defaults() == 125 # Uses defaults: 5^3
166-
assert keyword_with_defaults(x=2) == 8 # 2^3
167-
assert keyword_with_defaults(y=2) == 25 # 5^2
168-
assert keyword_with_defaults(x=3, y=4) == 81 # 3^4
132+
# Keyword-only function: must use keyword arguments
133+
assert keyword_only(x=4, y=5) == 20
134+
# Arguments after * cannot be passed positionally
135+
assert_raises_type_error(keyword_only, 4, 5)
169136

170-
# Must still use keyword syntax even when providing defaults
171-
keyword_default_error = False
172-
try:
173-
keyword_with_defaults(2, 3) # type: ignore [misc]
174-
except TypeError:
175-
keyword_default_error = True
176-
assert keyword_default_error is True
137+
# Mixed parameters demonstrate all three types
138+
assert mixed_parameters("first", "second", kw_only="third") == "first-second-third"
139+
assert mixed_parameters("first", pos_or_kw="second", kw_only="third") == "first-second-third"
140+
# Positional-only must be positional, keyword-only must be keyword
141+
assert_raises_type_error(mixed_parameters, pos_only="first", pos_or_kw="second", kw_only="third")
142+
assert_raises_type_error(mixed_parameters, "first", "second", "third")
143+
144+
# Positional-only with defaults still requires positional passing
145+
assert positional_with_defaults(5) == 15
146+
assert positional_with_defaults(5, 20) == 25
147+
assert_raises_type_error(positional_with_defaults, a=5, b=20)
148+
149+
# Keyword-only with defaults still requires keyword passing
150+
assert keyword_with_defaults() == 125
151+
assert keyword_with_defaults(x=2) == 8
152+
assert keyword_with_defaults(y=2) == 25
153+
assert keyword_with_defaults(x=3, y=4) == 81
154+
assert_raises_type_error(keyword_with_defaults, 2, 3)
177155

178156
# Complex signature: demonstrating all parameter types
179-
# Minimal call with required params only
180-
result3 = complex_signature(1, 2, 3, e=4)
181-
assert result3 == 40 # 1+2+3+10(default)+4+20(default)
182-
183-
# Providing all parameters
184-
result4 = complex_signature(1, 2, 3, 4, e=5, f=6)
185-
assert result4 == 21 # 1+2+3+4+5+6
186-
187-
# Middle parameter 'c' can be passed by keyword
188-
result5 = complex_signature(1, 2, c=3, e=4)
189-
assert result5 == 40
190-
191-
# Parameter 'd' can also be passed by keyword
192-
result6 = complex_signature(1, 2, 3, d=15, e=4)
193-
assert result6 == 45 # 1+2+3+15+4+20
194-
195-
# But 'a' and 'b' must be positional
196-
complex_error = False
197-
try:
198-
complex_signature(a=1, b=2, c=3, e=4) # type: ignore [call-arg]
199-
except TypeError:
200-
complex_error = True
201-
assert complex_error is True
202-
203-
# And 'e' must be keyword (even though 'f' has a default)
204-
complex_error2 = False
205-
try:
206-
complex_signature(1, 2, 3, 10, 4) # type: ignore [misc]
207-
except TypeError:
208-
complex_error2 = True
209-
assert complex_error2 is True
210-
211-
# Practical use case: Positional-only is great for functions where
212-
# parameter names are not meaningful or may change
213-
def distance(x1: float, y1: float, x2: float, y2: float, /) -> float:
214-
"""Calculate distance between two points.
215-
216-
The parameter names here are somewhat arbitrary (could be p1_x, etc.)
217-
so we make them positional-only to give us flexibility to rename them
218-
without breaking existing code.
219-
"""
220-
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
221-
157+
assert complex_signature(1, 2, 3, e=4) == 40
158+
assert complex_signature(1, 2, 3, 4, e=5, f=6) == 21
159+
assert complex_signature(1, 2, c=3, e=4) == 40
160+
assert complex_signature(1, 2, 3, d=15, e=4) == 45
161+
assert_raises_type_error(complex_signature, a=1, b=2, c=3, e=4)
162+
assert_raises_type_error(complex_signature, 1, 2, 3, 10, 4)
163+
164+
# Practical use case 1: Positional-only parameter renaming flexibility
222165
assert abs(distance(0, 0, 3, 4) - 5.0) < 0.01
223166

224-
# Practical use case: Keyword-only is great for boolean flags or
225-
# optional parameters where the intent should be clear at call site
226-
def create_user(username: str, *, admin: bool = False, active: bool = True, send_email: bool = False) -> dict[str, object]:
227-
"""Create a user with clear intent for optional parameters.
228-
229-
Making admin, active, and send_email keyword-only ensures that
230-
callers must specify exactly what they're setting, improving
231-
readability and preventing accidental mistakes.
232-
"""
233-
return {"username": username, "admin": admin, "active": active, "send_email": send_email}
234-
235-
# Clear intent at call site
167+
# Practical use case 2: Keyword-only clarity for optional flags
236168
user = create_user("john_doe", admin=True, send_email=True)
237169
assert user["admin"] is True
238-
assert user["active"] is True # Used default
170+
assert user["active"] is True
239171
assert user["send_email"] is True
240172

241173

‎ultimatepython/advanced/pattern_matching.py‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ def process_json_data(data: object) -> str:
226226
return "Invalid data"
227227

228228

229-
def main() -> None:
229+
def verify_literal_and_sequence_patterns() -> None:
230+
"""Verify literal values, status codes, tuples, and sequence matching."""
230231
# Test literal pattern matching
231232
assert classify_number(0) == "zero"
232233
assert classify_number(1) == "one"
@@ -257,6 +258,9 @@ def main() -> None:
257258
assert analyze_sequence([1, 2, 3, 4]) == "First: 1, Rest: [2, 3, 4]"
258259
assert analyze_sequence("not a list") == "Not a list"
259260

261+
262+
def verify_guard_and_class_patterns() -> None:
263+
"""Verify guard expressions and class-based object decomposition."""
260264
# Test pattern matching with guards
261265
assert process_command(["quit"]) == "Quitting"
262266
assert process_command(["go", "north"]) == "Going north"
@@ -293,6 +297,9 @@ def main() -> None:
293297
# Test unknown shape
294298
assert describe_shape("unknown") == "Unknown shape"
295299

300+
301+
def verify_mapping_and_advanced_patterns() -> None:
302+
"""Verify dictionary structural patterns, OR patterns, AS patterns, and nesting."""
296303
# Test dictionary pattern matching
297304
user1 = {"type": "user", "name": "Alice", "age": 30}
298305
assert process_json_data(user1) == "User Alice is 30 years old"
@@ -328,6 +335,17 @@ def main() -> None:
328335
assert analyze_nested([["single", 42]]) == "Single value: 42"
329336
assert analyze_nested("invalid") == "Unknown structure"
330337

338+
339+
def main() -> None:
340+
# 1. Literal and sequence pattern matching
341+
verify_literal_and_sequence_patterns()
342+
343+
# 2. Guard conditions and class pattern matching
344+
verify_guard_and_class_patterns()
345+
346+
# 3. Dictionary patterns, OR patterns, AS patterns, and nested structures
347+
verify_mapping_and_advanced_patterns()
348+
331349
# Pattern matching is particularly useful for parsing and handling
332350
# structured data like API responses, configuration files, or
333351
# abstract syntax trees in compilers/interpreters

0 commit comments

Comments
 (0)