Skip to content

Commit 2c65972

Browse files
committed
markdown source builds
Auto-generated via `{sandpaper}` Source : e6449a9 Branch : main Author : scottan <33283688+Scottan@users.noreply.github.com> Time : 2026-04-21 11:13:04 +0000 Message : Merge pull request #74 from UoMResearchIT/49-change-format-strings-into-f-strings 49 change format strings into f strings
1 parent 5169656 commit 2c65972

6 files changed

Lines changed: 128 additions & 77 deletions

File tree

01-introduction.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,63 @@ else:
189189

190190
:::::::::::::::::::::::::::::::::::::::::::::::
191191

192+
::::::::::::::::::::::::::::::::::::::::: callout
193+
194+
## Formatting Variables and Objects in Strings
195+
196+
Throughout this course, we will be printing the values of variables inside strings to demonstrate what the code does. There are a number of ways to this in Python; in this course we will be using `f-strings` which are the recommended string interpolation syntax from version 3.6 onwards.
197+
198+
To use `f-strings` simply start a string literal with `f` or `F`, then embed whatever you want interpolating into the string within curly braces `{}`:
199+
200+
```python
201+
two_int = 2
202+
two_str = "2"
203+
f_string = f"{two_int} + {two_str} = {2 + 2}"
204+
print(f_string)
205+
```
206+
```output
207+
2 + 2 = 4
208+
```
209+
210+
Numerical values can be formatted using `:` inside the curly braces. For example, an integer `i` can be made to have a width `n` using `{i:nd}`, or `{i:0nd}` to pad it out with zeros:
211+
212+
```python
213+
print(f"One with four leading spaces {1:5d}")
214+
print(f"One with four leading zeros {1:05d}")
215+
```
216+
```output
217+
One with four leading spaces 1
218+
One with four leading zeros 00001
219+
```
220+
221+
Floating point variables can have their precision specified with a number after a decimal point and an `f`:
222+
```python
223+
pi = 3.141592653589793
224+
print(pi)
225+
print(f"pi to three decimal places is {pi:.3f}")
226+
```
227+
```output
228+
3.141592653589793
229+
pi to three decimal places is 3.142
230+
```
231+
232+
Or made to use scientific notation with an `e`:
233+
234+
```python
235+
print(1e9)
236+
print(f"A billion in scientific notation is {1e9:.1e}")
237+
```
238+
```output
239+
1000000000.0
240+
A billion in scientific notation is 1.0e+09
241+
```
242+
243+
This is only scratching the surface of what you can do with `f-strings`, they are often the most powerful and concise way to format variables inside strings. However, there are occasions when other methods are preferable, and you should be careful using them with Python [before version 3.12](https://realpython.com/python-f-strings/#upgrading-f-strings-python-312-and-beyond).
244+
245+
To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/).
246+
247+
::::::::::::::::::::::::::::::::::::::::::::::::::
248+
192249
## Generative AI
193250

194251
We would like to reiterate the [Carpentries](https://carpentries.org/) stance on [Generative AI in coding](https://swcarpentry.github.io/python-novice-inflammation/01-intro.html#generative-ai) which you may have seen when preparing for this course.

02-dictionaries.md

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ Following the previous example, we can create a python dictionary using the name
117117

118118
```python
119119
d = {'alice': 35, 'bob': 18}
120-
```
121-
122-
```python
123120
print(d)
124121
```
125122

@@ -150,7 +147,7 @@ d4 = dict(zip(['jane','alice','bob'],[24,35,18]))
150147
To access an element of the dictionary we must use the *key*:
151148

152149
```python
153-
print('The age of alice is :', d['alice'])
150+
print(f'The age of alice is: {d["alice"]}')
154151
```
155152

156153
```output
@@ -161,8 +158,8 @@ We can also use a variable to index the dictionary:
161158

162159
```python
163160
key = 'alice'
164-
print('The name of the person is used as key:', key)
165-
print('The value associated to that key is:', d[key])
161+
print(f'The name of the person is used as key: {key}')
162+
print(f'The value associated to that key is: {d[key]}')
166163
```
167164

168165
```output
@@ -175,9 +172,9 @@ The value associated to that key is: 35
175172
Adding an element to a dictionary is done by creating a new key and attaching a value to it.
176173

177174
```python
178-
print('Original dictionary:', d)
175+
print(f'Original dictionary: {d}')
179176
d['jane'] = 24
180-
print('New dictionary:', d)
177+
print(f'New dictionary: {d}')
181178
```
182179

183180
```output
@@ -191,7 +188,7 @@ To add one or more new elements we can also use the `update` method:
191188
d_extra = {'tom': 54, 'david': 87}
192189

193190
d.update(d_extra)
194-
print('Updated dictionary:', d)
191+
print(f'Updated dictionary: {d}')
195192
```
196193

197194
```output
@@ -202,7 +199,7 @@ To delete an element, use the `del` method:
202199

203200
```python
204201
del d['tom']
205-
print('Dictionary with item deleted:', d)
202+
print(f'Dictionary with item deleted: {d}')
206203
```
207204

208205
```output
@@ -213,8 +210,8 @@ Alternatively, the `pop` function can be used to take an element out of a dictio
213210

214211
```python
215212
david_age = d.pop('david')
216-
print('Age of David:', david_age)
217-
print('Dictionary with david popped out:', d)
213+
print(f'Age of David: {david_age}')
214+
print(f'Dictionary with david popped out: {d}')
218215
```
219216

220217
```output
@@ -250,9 +247,9 @@ TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
250247
Keys have to be unique; you cannot have two keys with the same name. If you try to add an item using a key already present in the dictionary you will overwrite the previous value.
251248

252249
```python
253-
print('Original dictionary:', d)
250+
print(f'Original dictionary: {d}')
254251
d['alice'] = 12
255-
print('New dictionary:', d)
252+
print(f'New dictionary: {d}')
256253
```
257254

258255
```output
@@ -273,9 +270,9 @@ d1 = {'alice': 12, 'bob': 18, 'jane': 24, 'tom': 54, 'david': 87}
273270
d2 = {'tom': 54, 'david': 87}
274271
d3 = {'bob': 18, 'alice': 35, 'jane': 24}
275272
d4 = {'alice': 35, 'bob': 18, 'jane': 24}
276-
print('Dictionary 1 and dictionary 2 are equal:', d1 == d2)
277-
print('Dictionary 1 and dictionary 3 are equal:', d1 == d3)
278-
print('Dictionary 3 and dictionary 4 are equal:', d3 == d4)
273+
print(f'Dictionary 1 and dictionary 2 are equal: {d1 == d2}')
274+
print(f'Dictionary 1 and dictionary 3 are equal: {d1 == d3}')
275+
print(f'Dictionary 3 and dictionary 4 are equal: {d3 == d4}')
279276
```
280277

281278
```output
@@ -327,7 +324,7 @@ list(d.values())[0]
327324
```
328325

329326
It is also possible to iterate through the keys and items in the dictionary at the same time using the `items` function,
330-
which returns a *dict\_items* object containing `key, value` pairs:
327+
which returns a *dict\_items* object containing *key, value* pairs:
331328

332329
```python
333330
d.items()
@@ -341,7 +338,7 @@ This is very useful when using a dictionary in a `for` loop:
341338

342339
```python
343340
for key, value in d.items():
344-
print("Name:", key, " Age:", value)
341+
print(f'Name: {key}, Age: {value}')
345342
```
346343

347344
```output

03-numpy_essential.md

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -271,13 +271,12 @@ To identify any signal in the data we can use the standard deviation as an estim
271271
```python
272272
stddev_noisy = np.std(noisy)
273273
mean_noisy = np.mean(noisy)
274-
print(f'standard deviation is: {stddev_noisy}')
275-
print(f'mean value is: {mean_noisy}')
274+
print(f'standard deviation is: {stddev_noisy:.5f}')
275+
print(f'mean value is: {mean_noisy:.5f}')
276276
```
277-
278277
```output
279-
standard deviation is: 0.011592652442611553
280-
mean value is: 0.005047252119578472
278+
standard deviation is: 0.01159
279+
mean value is: 0.00505
281280
```
282281

283282
We will create a mask for the data, by selecting all data points below this threshold value (we'll assume here that any signal we might be interested in is positive):
@@ -394,10 +393,10 @@ To improve the visible output we will carry out some simple analysis of the imag
394393
First we examine the general stats of the data (using built-in methods, except for the median, which has to be called from NumPy directly):
395394

396395
```python
397-
print('mean value im1:', imdata.mean())
398-
print('median value im1:', np.median(imdata))
399-
print('max value im1:', imdata.max())
400-
print('min value im1:', imdata.min())
396+
print(f'mean value im1: {imdata.mean()}')
397+
print(f'median value im1: {np.median(imdata)}')
398+
print(f'max value im1: {imdata.max()}')
399+
print(f'min value im1: {imdata.min()}')
401400
```
402401

403402
```output
@@ -482,17 +481,17 @@ plt.imshow(immasked.mask, cmap='gray', origin='lower')
482481
This mask is applied to the data for all built-in functions. But where we have to directly use a NumPy function we have to make sure we use the equivalent function in the mask (`ma`) library:
483482

484483
```python
485-
print('original average:', imdata.mean())
486-
print('Masked average:', immasked.mean())
487-
print()
488-
print('original max:', imdata.max())
489-
print('Masked max:', immasked.max())
490-
print()
491-
print('original min:', imdata.min())
492-
print('Masked min:', immasked.min())
493-
print()
494-
print('original median:', np.mean(imdata))
495-
print('Masked median:', np.ma.median(immasked))
484+
print(f'original average: {imdata.mean()}')
485+
print(f'Masked average: {immasked.mean()}\n')
486+
487+
print(f'original max: {imdata.max()}')
488+
print(f'Masked max: {immasked.max()}\n')
489+
490+
print(f'original min: {imdata.min()}')
491+
print(f'Masked min: {immasked.min()}\n')
492+
493+
print(f'original median: {np.mean(imdata)}')
494+
print(f'Masked median: {np.ma.median(immasked)}')
496495
```
497496

498497
```output

05-defensive_programming.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ Please look at the following code. Can you find the fundamental problem in this
3434
val = 1
3535

3636
if val > 0:
37-
print('Value:', val, 'is positive.')
37+
print(f'Value: {val} is positive.')
3838
elif val == 0:
39-
print('Value:', val, 'is zero.')
39+
print(f'Value: {val} is zero.')
4040
else:
41-
print('Value:', val, 'is negative.')
41+
print(f'Value: {val} is negative.')
4242
```
4343

4444
::::::::::::::: solution
@@ -51,11 +51,11 @@ The test assumes that `val` is a number, and throws an uncontrolled error if it
5151
val = 'a'
5252

5353
if val > 0:
54-
print('Value:', val, 'is positive.')
54+
print(f'Value: {val} is positive.')
5555
elif val == 0:
56-
print('Value:', val, 'is zero.')
56+
print(f'Value: {val} is zero.')
5757
else:
58-
print('Value:', val, 'is negative.')
58+
print(f'Value: {val} is negative.')
5959
```
6060

6161
```output
@@ -64,9 +64,9 @@ TypeError Traceback (most recent call last)
6464
<ipython-input-2-99c0e25bf5e9> in <module>()
6565
1 def check_sign(val):
6666
----> 2 if val > 0:
67-
3 print('Value:', val, 'is positive.')
67+
3 print(f'Value: {val} is positive.')
6868
4 elif val == 0:
69-
5 print('Value:', val, 'is zero.')
69+
5 print(f'Value: {val} is zero.')
7070
7171
TypeError: '>' not supported between instances of 'str' and 'int'
7272
```
@@ -81,11 +81,11 @@ To make things simpler, we will first write the test as a function:
8181
```python
8282
def check_sign(val):
8383
if val > 0:
84-
print('Value:', val, 'is positive.')
84+
print(f'Value: {val} is positive.')
8585
elif val == 0:
86-
print('Value:', val, 'is zero.')
86+
print(f'Value: {val} is zero.')
8787
else:
88-
print('Value:', val, 'is negative.')
88+
print(f'Value: {val} is negative.')
8989
```
9090

9191
Then wrap the function call in an `if` statement:
@@ -121,7 +121,7 @@ try:
121121
except TypeError as err:
122122
print('Val is not a number')
123123
print('But our code does not crash anymore')
124-
print('The run-time error is:', err)
124+
print(f'The run-time error is: {err}')
125125
```
126126

127127
As with `if` statements, multiple `except` statements can be used, each with a different error test. These can be followed by an (optional) catch-all bare `except` statement (as we started with) to catch any unexpected errors. Note that only one `try` statement is allowed in the structure.
@@ -134,12 +134,12 @@ try:
134134
reciprocal = 1/val
135135
except TypeError as err:
136136
print('Val is not a number')
137-
print('The run-time error is:', err)
137+
print(f'The run-time error is: {err}')
138138
except Exception as err:
139139
print('Some error other than a TypeError occured')
140-
print('The run-time error is:', err)
140+
print(f'The run-time error is: {err}')
141141
else:
142-
print('The reciprocal of the value =', reciprocal)
142+
print(f'The reciprocal of the value = {reciprocal}')
143143
finally:
144144
print('release memory')
145145
```
@@ -214,7 +214,7 @@ To conduct such a test we can use an `assert` statement. This follows the struct
214214
```python
215215
val = 'a'
216216

217-
assert type(val) is float or type(val) is int, "Variable has to be a numerical object"
217+
assert type(val) is float or type(val) is int, 'Variable has to be a numerical object'
218218

219219
check_sign(val)
220220
```

0 commit comments

Comments
 (0)