Skip to content

Commit d0d9eaa

Browse files
committed
Merge remote-tracking branch 'origin/2025-learn'
2 parents 3bc4854 + fe2695f commit d0d9eaa

11 files changed

Lines changed: 241 additions & 0 deletions

2025/learn/1_master_core.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
def main() -> None:
2+
words = ["code", "python", "ai", "refactor", "bug"]
3+
4+
length_map: dict[str, int] = {}
5+
for word in words:
6+
if len(word) > 4:
7+
length_map[word] = len(word)
8+
9+
print(length_map)
10+
11+
# now with a dict comprehension
12+
length_map_comp = {word: len(word) for word in words if len(word) > 4}
13+
print(length_map_comp)
14+
15+
if __name__ == "__main__":
16+
main()

2025/learn/2_pythonic.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def main() -> None:
2+
names = ["Arjan", "Marieke", "Pim", "Sanne", "Daan", "Eva", "Lars"]
3+
4+
for i in range(len(names)):
5+
print(i, names[i])
6+
7+
# or more pythonic
8+
for index, name in enumerate(names):
9+
print(index, name)
10+
11+
if __name__ == "__main__":
12+
main()

2025/learn/3_build_tools.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from pathlib import Path
2+
3+
def rename_jpegs(folder: str):
4+
for file in Path(folder).glob("*.jpeg"):
5+
file.rename(file.with_suffix(".jpg"))

2025/learn/4_object_model.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def greet(name: str) -> str:
2+
return f"Hello, {name}!"
3+
4+
def main() -> None:
5+
say_hello = greet
6+
7+
print(say_hello("Pythonista"))
8+
9+
if __name__ == "__main__":
10+
main()

2025/learn/5_types_abstraction.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from typing import Protocol, Callable
2+
3+
class Logger(Protocol):
4+
def info(self, message: str) -> None: ...
5+
def error(self, message: str) -> None: ...
6+
7+
def process_order(order_id: int, logger: Logger) -> None:
8+
logger.info(f"Processing order {order_id}")
9+
10+
11+
ImageExporter = Callable[[bytes], None]
12+
13+
def export_image(data: bytes, exporter: ImageExporter) -> None:
14+
exporter(data)

2025/learn/6_design.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Protocol
2+
3+
def notify_user_no_di(user_email: str, message: str):
4+
print(f"Sending email to {user_email}: {message}")
5+
6+
7+
# Define a Protocol (interface) for notification services
8+
class Notifier(Protocol):
9+
def send(self, recipient: str, message: str) -> None:
10+
...
11+
12+
13+
# Concrete implementation: sends email
14+
class EmailNotifier:
15+
def send(self, recipient: str, message: str) -> None:
16+
print(f"[Email] To: {recipient} | Message: {message}")
17+
18+
19+
# Concrete implementation: sends SMS
20+
class SMSNotifier:
21+
def send(self, recipient: str, message: str) -> None:
22+
print(f"[SMS] To: {recipient} | Message: {message}")
23+
24+
25+
# Business logic function with injected dependency
26+
def notify_user(user: str, message: str, notifier: Notifier) -> None:
27+
notifier.send(user, message)
28+
29+
30+
def main() -> None:
31+
email_notifier = EmailNotifier()
32+
sms_notifier = SMSNotifier()
33+
34+
# Send email
35+
notify_user("alice@example.com", "Your invoice is ready.", email_notifier)
36+
37+
# Send SMS
38+
notify_user("+31612345678", "Your package is on the way!", sms_notifier)
39+
40+
41+
if __name__ == "__main__":
42+
main()

2025/learn/7_testing.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import pytest
2+
import sys
3+
4+
# Function we want to test
5+
def is_prime(n: int) -> bool:
6+
if n <= 1:
7+
return False
8+
for i in range(2, int(n**0.5) + 1):
9+
if n % i == 0:
10+
return False
11+
return True
12+
13+
14+
# Parametrized test: tests multiple inputs in one go
15+
@pytest.mark.parametrize("n, expected", [
16+
(2, True),
17+
(3, True),
18+
(4, False),
19+
(17, True),
20+
(18, False),
21+
(1, False),
22+
(0, False),
23+
(-5, False),
24+
])
25+
def test_is_prime(n: int, expected: bool) -> None:
26+
assert is_prime(n) == expected
27+
28+
29+
# Optional: run pytest programmatically from the same file
30+
if __name__ == "__main__":
31+
sys.exit(pytest.main([__file__]))

2025/learn/8_internals.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Countdown:
2+
def __init__(self, start: int):
3+
self.current = start
4+
5+
def __iter__(self):
6+
return self
7+
8+
def __next__(self):
9+
if self.current <= 0:
10+
raise StopIteration
11+
self.current -= 1
12+
return self.current + 1
13+
14+
def main() -> None:
15+
countdown = Countdown(5)
16+
for number in countdown:
17+
print(number)
18+
19+
if __name__ == "__main__":
20+
main()

2025/learn/9_standard.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import textwrap
2+
3+
4+
def main() -> None:
5+
text = "This is a sample text that will be wrapped to a specified width using the textwrap module in Python."
6+
print(textwrap.fill(text, width=40))
7+
8+
if __name__ == "__main__":
9+
main()

2025/learn/pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[project]
2+
name = "learning_python"
3+
version = "0.1.0"
4+
requires-python = ">=3.13"
5+
dependencies = [
6+
"pytest>=8.4.2",
7+
]

0 commit comments

Comments
 (0)