Skip to content

Commit a296a2e

Browse files
committed
add issue#28
1 parent 07b9207 commit a296a2e

File tree

3 files changed

+213
-7
lines changed

3 files changed

+213
-7
lines changed

issues/28.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# pycobytes[28] := Breaking Specificity
2+
<!-- #SQUARK live!
3+
| dest = issues/(issue)/28
4+
| title = Breaking Specificity
5+
| head = Breaking Specificity
6+
| index = 28
7+
| tags = keywords
8+
| date = 2025 May 13
9+
-->
10+
11+
> *To understand recursion, one must first understand recursion.*
12+
13+
Hey pips!
14+
15+
If you’ve ever found yourself needing to exit out of a loop early, you can do that with the `break` keyword.
16+
17+
```py
18+
>>> for i in range(1, 999, 4):
19+
print(i)
20+
21+
if i > 10:
22+
break
23+
1
24+
5
25+
9
26+
13
27+
```
28+
29+
Simple as that. It just terminates the loop there and then.
30+
31+
A common example of where you might see this is in a simple linear search:
32+
33+
```py
34+
def find_first_active_pair(database: dict):
35+
out = []
36+
37+
for profile in database.values():
38+
if profile.is_active():
39+
out.append(profile)
40+
41+
if len(profile) == 2:
42+
break # exits the for loop
43+
44+
return out
45+
```
46+
47+
This of course also works for (hah) the `while` loop. If you ever see `while True:`, there’s a good chance it’ll have a `break` inside to prevent the program from running indefinitely.
48+
49+
```py
50+
>>> while True:
51+
k = random.randint(1, 10)
52+
if k == 10:
53+
break
54+
else:
55+
print(k)
56+
57+
2
58+
7
59+
1
60+
5
61+
1
62+
9
63+
```
64+
65+
Now `while` does inherently have a condition after it, but this condition is only checked at the *start* of each iteration. Sometimes, especially with more complex loops, you may want to check many conditions throughout the loop, maybe at different points.
66+
67+
```py
68+
while game.state = "running":
69+
if 0 >= player.health:
70+
# this won’t immediately exit the loop
71+
game.state = "over"
72+
73+
# so we can force an exit
74+
break
75+
76+
game.tick()
77+
```
78+
79+
Having `break` here gives you flexibility and more control over when you exit the loop.
80+
81+
Did you know, there’s a little-known keyword combo in Python – the **for-else** loop. You heard me right.
82+
83+
```py
84+
for cell in mind:
85+
cell.blown()
86+
else:
87+
print("whattttt")
88+
```
89+
90+
Not quite your average if-else block, eh?
91+
92+
The code inside `else` here only runs if the loop fully finishes – i.e. it did not encounter any `break`, so every iteration was ran.
93+
94+
This one’s quite niche. It’s good for edge cases:
95+
96+
```py
97+
def find_user(id: int, database: dict)
98+
found = None
99+
100+
for profile in database.values():
101+
if profile.id = id:
102+
found = profile
103+
break
104+
else:
105+
raise UserNotFoundError(f"Did not find user #{id}")
106+
107+
found.check()
108+
found.sanitise()
109+
return found
110+
```
111+
112+
You may notice here that we could have totally achieved the same thing by just `return`-ing straight from the loop, and we wouldn’t need the for-else...
113+
114+
```py
115+
def find_user(id: int, database: dict)
116+
for profile in database.values():
117+
if profile.id = id:
118+
profile.check()
119+
profile.sanitise()
120+
return profile
121+
122+
raise UserNotFoundError(f"Did not find user #{id}")
123+
```
124+
125+
These are both examples of short-circuiting – exiting something early to avoid doing unnecessary work. In this case I’d say using `return` is definitely cleaner than the for-else. In fact, leveraging functions and `return` is a really powerful way of handling code that needs to ‘stop’ early. Probably part of the reason why you don’t see for-else at all is because you can achieve the same thing with just a function.
126+
127+
Alright, 1 more keyword for you. If you ever need to end the current iteration but not exit the loop entirely, you can ‘skip’ to the next iteration with `continue`:
128+
129+
```py
130+
def find_good_pet(database: dict):
131+
for profile in database.values():
132+
if profile.pets is None:
133+
continue
134+
135+
ranked = sorted(
136+
profile.pets,
137+
key = lambda pet: pet.happiness,
138+
reverse = True
139+
)
140+
141+
return ranked[0]
142+
```
143+
144+
This skips over the rest of the code in the loop and moves straight on to the next iteration.
145+
146+
`continue` is less obviously named than `break` (`skip` or `next` would probably have been better), but hey.
147+
148+
149+
<br>
150+
151+
152+
## Challenge
153+
154+
Given a list of numbers, can you find the **first 3** that are odd square numbers with more than 1 digit?
155+
156+
```py
157+
>>> l = [1, 9, 6, 15, 25, 3, 81, 0, -1, 49, 169, 196]
158+
>>> (your_code)
159+
[25, 81, 49]
160+
```
161+
162+
163+
<br>
164+
165+
166+
---
167+
168+
<div align="center">
169+
170+
[![The Codeless Code, Case 129](../assets/issues/28-codeless.png)](http://thecodelesscode.com/case/129)
171+
172+
[*The Codeless Code*, Case 129](http://thecodelesscode.com/case/129)
173+
174+
</div>

site/scss-config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// SCSS Config
2-
/// Last generated 24 April 2025
2+
/// Last generated 13 May 2025
33

44
const scssConfig = {
55
prependData: `

site/src/data/site.json

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"meta": {
3-
"exported": "2025-05-09",
4-
"file_count": 32,
5-
"page_count": 31
3+
"exported": "2025-05-13",
4+
"file_count": 33,
5+
"page_count": 32
66
},
77
"index": {
88
"01": {
@@ -167,6 +167,12 @@
167167
"issues/27.md"
168168
]
169169
},
170+
"28": {
171+
"route": null,
172+
"pages": [
173+
"issues/28.md"
174+
]
175+
},
170176
"404": {
171177
"route": null,
172178
"pages": [
@@ -265,6 +271,9 @@
265271
"26": [
266272
"issues/26.md"
267273
],
274+
"keywords": [
275+
"issues/28.md"
276+
],
268277
"special": [
269278
"issues/404.md"
270279
]
@@ -953,9 +962,9 @@
953962
},
954963
"issues/27.md": {
955964
"path": "issues/27.md",
956-
"last_deploy": "2025-05-09 08:00:27 +0100",
957-
"slocs": 124,
958-
"chars": 4158,
965+
"last_deploy": "2025-05-09 09:34:26 +0100",
966+
"slocs": 132,
967+
"chars": 4293,
959968
"isIndex": false,
960969
"flags": [
961970
"live"
@@ -975,6 +984,29 @@
975984
"date": "2025-05-09",
976985
"date_display": "2025 May 9"
977986
},
987+
"issues/28.md": {
988+
"path": "issues/28.md",
989+
"last_deploy": "2025-05-13 12:30:40 +0100",
990+
"slocs": 176,
991+
"chars": 4618,
992+
"isIndex": false,
993+
"flags": [
994+
"live"
995+
],
996+
"dest": "issues/(issue)/28",
997+
"title": "Breaking Specificity",
998+
"head": "Breaking Specificity",
999+
"capt": null,
1000+
"desc": null,
1001+
"index": [
1002+
"28"
1003+
],
1004+
"tags": [
1005+
"keywords"
1006+
],
1007+
"date": "2025-05-13",
1008+
"date_display": "2025 May 13"
1009+
},
9781010
"issues/404.md": {
9791011
"path": "issues/404.md",
9801012
"last_deploy": "2025-04-24 10:29:17 +0100",

0 commit comments

Comments
 (0)