From 976c42de1777266624b802c8718ddd890dca8048 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Fri, 17 Apr 2026 14:49:22 +0100 Subject: [PATCH 01/18] fix: converted .format() uses into f strings --- episodes/06-units_and_quantities.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/episodes/06-units_and_quantities.md b/episodes/06-units_and_quantities.md index 03f3cbd..55475d4 100644 --- a/episodes/06-units_and_quantities.md +++ b/episodes/06-units_and_quantities.md @@ -296,7 +296,7 @@ We can see from this that the degree unit is `u.deg`, so we can use this to defi ```python angle = 90 * u.deg -print('angle in degrees: {}; and in radians: {}'.format(angle.value,angle.to(u.rad).value)) +print(f'angle in degrees: {angle.value}; and in radians: {angle.to(u.rad).value}') ``` ```output @@ -306,9 +306,9 @@ angle in degrees: 90.0; and in radians: 1.5707963267948966 Now we can pass the angle directly to `np.sin` without having to convert directly to radians: ```python -print('sin of 90 degrees is: {}'.format(np.sin(angle))) -print('sin of pi/2 radians is: {}'.format(np.sin(1.57079632))) -print('sin of 90 degrees is not: {}'.format(np.sin(90))) +print(f'sin of 90 degrees is: {np.sin(angle)}') +print(f'sin of pi/2 radians is: {np.sin(1.57079632)}') +print(f'sin of 90 degrees is not: {np.sin(90)}') ``` ```output @@ -362,7 +362,8 @@ Each of the temperature scales is considered as using an irreducible unit in sta ```python t2 = 1 * u.deg_C -print('{} is equivalent to {}'.format(t2,t2.to(imperial.Fahrenheit, equivalencies=u.temperature()))) +t2_deg_f = t2.to(imperial.Fahrenheit, equivalencies=u.temperature()) +print(f'{t2} is equivalent to {t2_deg_f}') ``` ```output @@ -376,19 +377,16 @@ To get the incremental value of 1 degree Celsius in Fahrenheit we would need to ```python t1 = 0 * u.deg_C t2 = 1 * u.deg_C -print('{} increment is equivalent to a {} increment'.format( - t2 - t1, - t2.to(imperial.Fahrenheit,equivalencies=u.temperature()) - - t1.to(imperial.Fahrenheit, equivalencies=u.temperature()) - ) -) +t1_deg_f = t1.to(imperial.Fahrenheit, equivalencies=u.temperature()) +t2_deg_f = t2.to(imperial.Fahrenheit,equivalencies=u.temperature()) +print(f'{t2 - t1} increment is equivalent to a {t2_deg_f - t1_deg_f} increment') ``` ```output 1.0 deg_C increment is equivalent to a 1.7999999999999972 deg_F increment ``` -This is verging on unreadable (as is demonstrated by us having to split a simple arithmetic expression involving two variables across two lines of code). +This is verging on unreadable (as is demonstrated by us having to split a simple arithmetic expression involving two variables across several lines of code). Fortunately there is support for cleaner temperature conversions in the [pint](https://pint.readthedocs.io/en/latest/index.html) package. This has similar functionality to the `astropy.unit` package, but has been built from the ground up with a focus on different aspects. These include unit parsing and standalone unit definitions, uncertainties integration, and (important for our example here), cleaner treatment of temperature units. @@ -411,7 +409,7 @@ This library has the temperature units as before: ```python t2 = 1 * ureg.degC -print('{} is equivalent to {}'.format(t2,t2.to(ureg.degF))) +print(f'{t2} is equivalent to {t2.to(ureg.degF)}') ``` ```output @@ -422,7 +420,7 @@ But it also includes the concept of temperature increments: ```python deltaT = 1 * ureg.delta_degC -print('{} is equivalent to {}'.format(deltaT,deltaT.to(ureg.delta_degF))) +print(f'{deltaT} is equivalent to {deltaT.to(ureg.delta_degF)}') ``` ```output From ca8326777353e2bb99bbdf89c18a495b5da89e96 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Fri, 17 Apr 2026 21:33:01 +0100 Subject: [PATCH 02/18] feat: new callout inside introduction on f-strings --- episodes/01-introduction.md | 59 +++++++++++++++++++++++++++++++++++++ episodes/02-dictionaries.md | 46 +++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index ec8d354..3c4c97b 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -189,6 +189,64 @@ else: ::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::: callout + +## Formatting Variables and Objects in Strings + +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 recomended string interpollation syntax from version 3.6 onwards. + +To use `f-strings` simply start a string literal with `f` or `F`, then embed whatever you want interpollating into the string within curly braces `{}`: + +```python +two_int = 2 +two_str = "2" +f_string = f"{two_int} + {two_str} = {2 + 2}" +print(f_string) +``` +```output +2 + 2 = 4 +``` + +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: + +```python +print(f"One with four leading spaces {1:5d}") +print(f"One with four leading zeros {1:05d}") +``` +```output +One with four leading spaces 1 +One with four leading zeros 00001 +``` + +Floating point variables can have their precision specified with a number after a decimal point and an `f`: +```python +pi = 3.141592653589793 +print(pi) +print(f"pi to three decimal places is {pi:.3f}") +``` +```output +3.141592653589793 +pi to three decimal places is 3.142 +``` + +Or made to use scientific notation with an `e`: + +```python +print(1e9) +print(f"A billion in scientific notation is {1e9:.1e}") +``` +```output +1000000000.0 +A billion in scientific notation is 1.0e+09 +``` + +This is only scratching the surface of what `f-strings` are capable of, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). + +To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::: callout :::::::::::::::::::::::::::::::::::::::: keypoints @@ -197,6 +255,7 @@ else: - indexing - loops - conditionals +- string formatting :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/02-dictionaries.md b/episodes/02-dictionaries.md index 6284780..13f1ec1 100644 --- a/episodes/02-dictionaries.md +++ b/episodes/02-dictionaries.md @@ -117,9 +117,6 @@ Following the previous example, we can create a python dictionary using the name ```python d = {'alice': 35, 'bob': 18} -``` - -```python print(d) ``` @@ -170,6 +167,49 @@ The name of the person is used as key: alice The value associated to that key is: 35 ``` +::::::::::::::::::::::::::::::::::::::::: callout + +## Formatting Variables and Objects in Strings + +Here and elsewhere in the course, we will be printing the values of variables inside strings to understand what the actions we are demostrating do. There are a number of ways to this in Python. In this course, we will be using `f-strings`, which are the recomended string interpollation syntax from Python version 3.6 onwards. + +To use `f-strings` simply start a string literal with `f` or `F`, then embed any variable you want interpollating into the string within curly braces `{}`. + +```python +two = 2 +f_string = f"{two} + {2} = {two + 2}" +print(f_string) +``` + +Numerical values can be formatted ":" to have particular decimal places + +```python +pi = 3.141592653589793 +print(pi) +print(f"pi to three decimal places is {pi:.3f}") +``` +```output +3.141592653589793 +pi to three decimal places is 3.142 +``` +```python +print(1e9) +print(f"A billion in scientific notation is {1e9:.1e}") +``` +```output +1000000000.0 +A billion in E notation is 1.0e+09 +``` + +This is only scratching the surface of what `f-strings` are capable of, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). + +To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::: callout + + ### Adding and deleting elements Adding an element to a dictionary is done by creating a new key and attaching a value to it. From 0951687710b14fbce999b684adbebb08ab76d2b0 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Sun, 19 Apr 2026 20:49:50 +0100 Subject: [PATCH 03/18] feat: box on f-strings added to intro --- episodes/01-introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 3c4c97b..ea04c91 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -193,7 +193,7 @@ else: ## Formatting Variables and Objects in Strings -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 recomended string interpollation syntax from version 3.6 onwards. +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 interpollation syntax from version 3.6 onwards. To use `f-strings` simply start a string literal with `f` or `F`, then embed whatever you want interpollating into the string within curly braces `{}`: @@ -240,7 +240,7 @@ print(f"A billion in scientific notation is {1e9:.1e}") A billion in scientific notation is 1.0e+09 ``` -This is only scratching the surface of what `f-strings` are capable of, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). +This is only scratching the surface of what you can do with `f-strings`, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). From 3f0fa6573562cdf4a2a35ae9961778989e2f847e Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Sun, 19 Apr 2026 21:01:34 +0100 Subject: [PATCH 04/18] fix: used f strings in dictionarieis chapter --- episodes/02-dictionaries.md | 75 ++++++++----------------------------- 1 file changed, 16 insertions(+), 59 deletions(-) diff --git a/episodes/02-dictionaries.md b/episodes/02-dictionaries.md index 13f1ec1..cd0b512 100644 --- a/episodes/02-dictionaries.md +++ b/episodes/02-dictionaries.md @@ -147,7 +147,7 @@ d4 = dict(zip(['jane','alice','bob'],[24,35,18])) To access an element of the dictionary we must use the *key*: ```python -print('The age of alice is :', d['alice']) +print(f'The age of alice is: {d["alice"]}') ``` ```output @@ -158,8 +158,8 @@ We can also use a variable to index the dictionary: ```python key = 'alice' -print('The name of the person is used as key:', key) -print('The value associated to that key is:', d[key]) +print(f'The name of the person is used as key: {key}') +print(f'The value associated to that key is: {d[key]}') ``` ```output @@ -167,57 +167,14 @@ The name of the person is used as key: alice The value associated to that key is: 35 ``` -::::::::::::::::::::::::::::::::::::::::: callout - -## Formatting Variables and Objects in Strings - -Here and elsewhere in the course, we will be printing the values of variables inside strings to understand what the actions we are demostrating do. There are a number of ways to this in Python. In this course, we will be using `f-strings`, which are the recomended string interpollation syntax from Python version 3.6 onwards. - -To use `f-strings` simply start a string literal with `f` or `F`, then embed any variable you want interpollating into the string within curly braces `{}`. - -```python -two = 2 -f_string = f"{two} + {2} = {two + 2}" -print(f_string) -``` - -Numerical values can be formatted ":" to have particular decimal places - -```python -pi = 3.141592653589793 -print(pi) -print(f"pi to three decimal places is {pi:.3f}") -``` -```output -3.141592653589793 -pi to three decimal places is 3.142 -``` -```python -print(1e9) -print(f"A billion in scientific notation is {1e9:.1e}") -``` -```output -1000000000.0 -A billion in E notation is 1.0e+09 -``` - -This is only scratching the surface of what `f-strings` are capable of, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). - -To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). - -:::::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::::::::::::::::::::::::::: callout - - ### Adding and deleting elements Adding an element to a dictionary is done by creating a new key and attaching a value to it. ```python -print('Original dictionary:', d) +print(f'Original dictionary: {d}') d['jane'] = 24 -print('New dictionary:', d) +print(f'New dictionary: {d}') ``` ```output @@ -231,7 +188,7 @@ To add one or more new elements we can also use the `update` method: d_extra = {'tom': 54, 'david': 87} d.update(d_extra) -print('Updated dictionary:', d) +print(f'Updated dictionary: {d}') ``` ```output @@ -242,7 +199,7 @@ To delete an element, use the `del` method: ```python del d['tom'] -print('Dictionary with item deleted:', d) +print(f'Dictionary with item deleted: {d}') ``` ```output @@ -253,8 +210,8 @@ Alternatively, the `pop` function can be used to take an element out of a dictio ```python david_age = d.pop('david') -print('Age of David:', david_age) -print('Dictionary with david popped out:', d) +print(f'Age of David: {david_age}') +print(f'Dictionary with david popped out: {d}') ``` ```output @@ -290,9 +247,9 @@ TypeError: unsupported operand type(s) for +: 'dict' and 'dict' 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. ```python -print('Original dictionary:', d) +print(f'Original dictionary: {d}') d['alice'] = 12 -print('New dictionary:', d) +print(f'New dictionary: {d}') ``` ```output @@ -313,9 +270,9 @@ d1 = {'alice': 12, 'bob': 18, 'jane': 24, 'tom': 54, 'david': 87} d2 = {'tom': 54, 'david': 87} d3 = {'bob': 18, 'alice': 35, 'jane': 24} d4 = {'alice': 35, 'bob': 18, 'jane': 24} -print('Dictionary 1 and dictionary 2 are equal:', d1 == d2) -print('Dictionary 1 and dictionary 3 are equal:', d1 == d3) -print('Dictionary 3 and dictionary 4 are equal:', d3 == d4) +print(f'Dictionary 1 and dictionary 2 are equal: {d1 == d2}') +print(f'Dictionary 1 and dictionary 3 are equal: {d1 == d3}') +print(f'Dictionary 3 and dictionary 4 are equal: {d3 == d4}') ``` ```output @@ -367,7 +324,7 @@ list(d.values())[0] ``` It is also possible to iterate through the keys and items in the dictionary at the same time using the `items` function, -which returns a *dict\_items* object containing `key, value` pairs: +which returns a *dict\_items* object containing *key, value* pairs: ```python d.items() @@ -381,7 +338,7 @@ This is very useful when using a dictionary in a `for` loop: ```python for key, value in d.items(): - print("Name:", key, " Age:", value) + print(f'Name: {key}, Age: {value}') ``` ```output From f913c2b874d8eecc4a3a0f1655a03c5250ec9c78 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Sun, 19 Apr 2026 21:10:10 +0100 Subject: [PATCH 05/18] fix: used f-strings in numpy essentials --- episodes/03-numpy_essential.md | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/episodes/03-numpy_essential.md b/episodes/03-numpy_essential.md index 1d93da8..f07fc1b 100644 --- a/episodes/03-numpy_essential.md +++ b/episodes/03-numpy_essential.md @@ -271,13 +271,12 @@ To identify any signal in the data we can use the standard deviation as an estim ```python stddev_noisy = np.std(noisy) mean_noisy = np.mean(noisy) -print(f'standard deviation is: {stddev_noisy}') -print(f'mean value is: {mean_noisy}') +print(f'standard deviation is: {stddev_noisy:.5f}') +print(f'mean value is: {mean_noisy:.5f}') ``` - ```output -standard deviation is: 0.011592652442611553 -mean value is: 0.005047252119578472 +standard deviation is: 0.01159 +mean value is: 0.00505 ``` 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 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): ```python -print('mean value im1:', imdata.mean()) -print('median value im1:', np.median(imdata)) -print('max value im1:', imdata.max()) -print('min value im1:', imdata.min()) +print(f'mean value im1: {imdata.mean()}') +print(f'median value im1: {np.median(imdata)}') +print(f'max value im1: {imdata.max()}') +print(f'min value im1: {imdata.min()}') ``` ```output @@ -482,17 +481,17 @@ plt.imshow(immasked.mask, cmap='gray', origin='lower') 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: ```python -print('original average:', imdata.mean()) -print('Masked average:', immasked.mean()) -print() -print('original max:', imdata.max()) -print('Masked max:', immasked.max()) -print() -print('original min:', imdata.min()) -print('Masked min:', immasked.min()) -print() -print('original median:', np.mean(imdata)) -print('Masked median:', np.ma.median(immasked)) +print(f'original average: {imdata.mean()}') +print(f'Masked average: {immasked.mean()}\n') + +print(f'original max: {imdata.max()}') +print(f'Masked max: {immasked.max()}\n') + +print(f'original min: {imdata.min()}') +print(f'Masked min: {immasked.min()}\n') + +print(f'original median: {np.mean(imdata)}') +print(f'Masked median: {np.ma.median(immasked)}') ``` ```output From 0b22919e96b623fcdef470405387f10ec36cdb89 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Sun, 19 Apr 2026 21:17:17 +0100 Subject: [PATCH 06/18] used f-strings in chapter 5 --- episodes/05-defensive_programming.md | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/episodes/05-defensive_programming.md b/episodes/05-defensive_programming.md index 5722bf9..c85e28e 100644 --- a/episodes/05-defensive_programming.md +++ b/episodes/05-defensive_programming.md @@ -34,11 +34,11 @@ Please look at the following code. Can you find the fundamental problem in this val = 1 if val > 0: - print('Value:', val, 'is positive.') + print(f'Value: {val} is positive.') elif val == 0: - print('Value:', val, 'is zero.') + print(f'Value: {val} is zero.') else: - print('Value:', val, 'is negative.') + print(f'Value: {val} is negative.') ``` ::::::::::::::: solution @@ -51,11 +51,11 @@ The test assumes that `val` is a number, and throws an uncontrolled error if it val = 'a' if val > 0: - print('Value:', val, 'is positive.') + print(f'Value: {val} is positive.') elif val == 0: - print('Value:', val, 'is zero.') + print(f'Value: {val} is zero.') else: - print('Value:', val, 'is negative.') + print(f'Value: {val} is negative.') ``` ```output @@ -64,9 +64,9 @@ TypeError Traceback (most recent call last) in () 1 def check_sign(val): ----> 2 if val > 0: - 3 print('Value:', val, 'is positive.') + 3 print(f'Value: {val} is positive.') 4 elif val == 0: - 5 print('Value:', val, 'is zero.') + 5 print(f'Value: {val} is zero.') TypeError: '>' not supported between instances of 'str' and 'int' ``` @@ -81,11 +81,11 @@ To make things simpler, we will first write the test as a function: ```python def check_sign(val): if val > 0: - print('Value:', val, 'is positive.') + print(f'Value: {val} is positive.') elif val == 0: - print('Value:', val, 'is zero.') + print(f'Value: {val} is zero.') else: - print('Value:', val, 'is negative.') + print(f'Value: {val} is negative.') ``` Then wrap the function call in an `if` statement: @@ -121,7 +121,7 @@ try: except TypeError as err: print('Val is not a number') print('But our code does not crash anymore') - print('The run-time error is:', err) + print(f'The run-time error is: {err}') ``` 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: reciprocal = 1/val except TypeError as err: print('Val is not a number') - print('The run-time error is:', err) + print(f'The run-time error is: {err}') except Exception as err: print('Some error other than a TypeError occured') - print('The run-time error is:', err) + print(f'The run-time error is: {err}') else: - print('The reciprocal of the value =', reciprocal) + print(f'The reciprocal of the value = {reciprocal}') finally: print('release memory') ``` @@ -214,7 +214,7 @@ To conduct such a test we can use an `assert` statement. This follows the struct ```python val = 'a' -assert type(val) is float or type(val) is int, "Variable has to be a numerical object" +assert type(val) is float or type(val) is int, 'Variable has to be a numerical object' check_sign(val) ``` From 8ccd5415b4c8dc32aaa958ff88ed1a4a3b19dfee Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Sun, 19 Apr 2026 21:22:39 +0100 Subject: [PATCH 07/18] fix: added some precisions in chapter 6 to neaten p print statements --- episodes/06-units_and_quantities.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/episodes/06-units_and_quantities.md b/episodes/06-units_and_quantities.md index 55475d4..dfa33f2 100644 --- a/episodes/06-units_and_quantities.md +++ b/episodes/06-units_and_quantities.md @@ -379,11 +379,11 @@ t1 = 0 * u.deg_C t2 = 1 * u.deg_C t1_deg_f = t1.to(imperial.Fahrenheit, equivalencies=u.temperature()) t2_deg_f = t2.to(imperial.Fahrenheit,equivalencies=u.temperature()) -print(f'{t2 - t1} increment is equivalent to a {t2_deg_f - t1_deg_f} increment') +print(f'{t2 - t1} increment is equivalent to a {t2_deg_f - t1_deg_f:.1f} increment') ``` ```output -1.0 deg_C increment is equivalent to a 1.7999999999999972 deg_F increment +1.0 deg_C increment is equivalent to a 1.8 deg_F increment ``` This is verging on unreadable (as is demonstrated by us having to split a simple arithmetic expression involving two variables across several lines of code). @@ -409,22 +409,22 @@ This library has the temperature units as before: ```python t2 = 1 * ureg.degC -print(f'{t2} is equivalent to {t2.to(ureg.degF)}') +print(f'{t2} is equivalent to {t2.to(ureg.degF):.1f}') ``` ```output -1 degree_Celsius is equivalent to 33.79999999999993 degree_Fahrenheit +1 degree_Celsius is equivalent to 33.8 degree_Fahrenheit ``` But it also includes the concept of temperature increments: ```python deltaT = 1 * ureg.delta_degC -print(f'{deltaT} is equivalent to {deltaT.to(ureg.delta_degF)}') +print(f'{deltaT} is equivalent to {deltaT.to(ureg.delta_degF):.1f}') ``` ```output -1 delta_degree_Celsius is equivalent to 1.7999999999999998 delta_degree_Fahrenheit +1 delta_degree_Celsius is equivalent to 1.8 delta_degree_Fahrenheit ``` Because of the popularity of python this overlap of functionality of packages can be common. We would recommend exploring the different available packages that might cover your requirements before settling on one. And keep watching out for new packages, and be prepared to switch when starting new projects if/when you find better packages. From a606af0e2077db11fa7ddc0f26db8c8978267a96 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:18:44 +0100 Subject: [PATCH 08/18] fix: corrected typos --- episodes/01-introduction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index ea04c91..075066e 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -193,9 +193,9 @@ else: ## Formatting Variables and Objects in Strings -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 interpollation syntax from version 3.6 onwards. +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. -To use `f-strings` simply start a string literal with `f` or `F`, then embed whatever you want interpollating into the string within curly braces `{}`: +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 `{}`: ```python two_int = 2 @@ -240,7 +240,7 @@ print(f"A billion in scientific notation is {1e9:.1e}") A billion in scientific notation is 1.0e+09 ``` -This is only scratching the surface of what you can do with `f-strings`, they are often the most powerful and conside way to format variables inside strings. However, there are occations 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). +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). To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). From a5cbdac412b7602019d12b0e7c885fa29d354ad2 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:23:58 +0100 Subject: [PATCH 09/18] fix: Added Genertive AI text to stop conflict --- episodes/01-introduction.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 075066e..a590484 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -248,6 +248,16 @@ To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/) ::::::::::::::::::::::::::::::::::::::::: callout +## Generative AI + +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. + +To summarise the position, the recommendation is that you **avoid** getting help from generative AI during the workshop for several reasons: + + - For most problems you will encounter at this stage, help and answers can be found among the first results returned by searching the internet or looking on e.g. [StackOverflow](https://stackoverflow.com/questions). + - The foundational knowledge and skills you will learn in this lesson by writing and fixing your own programs are essential to be able to evaluate the correctness and safety of any code you receive from online help or a generative AI chatbot. If you choose to use these tools in the future, the expertise you gain from learning and practising these fundamentals on your own will help you use them more effectively. + - As you continue programming, the mistakes you make will be the kinds that have also been made – and overcome! – by everybody else who learned to program before you. Since these mistakes and the questions you are likely to have at this stage are common, they are also better represented than other, more specialised problems and tasks in the data that was used to train generative AI tools. This means that a generative AI chatbot is more likely to produce accurate responses to questions that novices ask, which could give you a false impression of how reliable they will be when you are ready to do things that are more advanced. + :::::::::::::::::::::::::::::::::::::::: keypoints - variables From d5f89a44b4e4bd309de2bf8227ab485310082485 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:25:21 +0100 Subject: [PATCH 10/18] feat: added point on gen-AI in keypoints section --- episodes/01-introduction.md | 1 + 1 file changed, 1 insertion(+) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index a590484..490f85b 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -266,6 +266,7 @@ To summarise the position, the recommendation is that you **avoid** getting help - loops - conditionals - string formatting +- avoid using generative AI during this course :::::::::::::::::::::::::::::::::::::::::::::::::: From ab11718946ff1773f7cfcbfd999a05a97f86cb2b Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:41:07 +0100 Subject: [PATCH 11/18] reverted keypoints changes to avoid clash with #77 --- episodes/01-introduction.md | 60 ------------------------------------- 1 file changed, 60 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 490f85b..d58305d 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -189,65 +189,6 @@ else: ::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::::: callout - -## Formatting Variables and Objects in Strings - -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. - -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 `{}`: - -```python -two_int = 2 -two_str = "2" -f_string = f"{two_int} + {two_str} = {2 + 2}" -print(f_string) -``` -```output -2 + 2 = 4 -``` - -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: - -```python -print(f"One with four leading spaces {1:5d}") -print(f"One with four leading zeros {1:05d}") -``` -```output -One with four leading spaces 1 -One with four leading zeros 00001 -``` - -Floating point variables can have their precision specified with a number after a decimal point and an `f`: -```python -pi = 3.141592653589793 -print(pi) -print(f"pi to three decimal places is {pi:.3f}") -``` -```output -3.141592653589793 -pi to three decimal places is 3.142 -``` - -Or made to use scientific notation with an `e`: - -```python -print(1e9) -print(f"A billion in scientific notation is {1e9:.1e}") -``` -```output -1000000000.0 -A billion in scientific notation is 1.0e+09 -``` - -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). - -To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). - -:::::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::::::::::::::::::::::::::: callout - ## Generative AI 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. @@ -266,7 +207,6 @@ To summarise the position, the recommendation is that you **avoid** getting help - loops - conditionals - string formatting -- avoid using generative AI during this course :::::::::::::::::::::::::::::::::::::::::::::::::: From 2c9d38cdd1a20d30e236753ebf5fcda8dba7dd7e Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:45:18 +0100 Subject: [PATCH 12/18] Revert "reverted keypoints changes to avoid clash with #77" This reverts commit ab11718946ff1773f7cfcbfd999a05a97f86cb2b. --- episodes/01-introduction.md | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index d58305d..490f85b 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -189,6 +189,65 @@ else: ::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::: callout + +## Formatting Variables and Objects in Strings + +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. + +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 `{}`: + +```python +two_int = 2 +two_str = "2" +f_string = f"{two_int} + {two_str} = {2 + 2}" +print(f_string) +``` +```output +2 + 2 = 4 +``` + +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: + +```python +print(f"One with four leading spaces {1:5d}") +print(f"One with four leading zeros {1:05d}") +``` +```output +One with four leading spaces 1 +One with four leading zeros 00001 +``` + +Floating point variables can have their precision specified with a number after a decimal point and an `f`: +```python +pi = 3.141592653589793 +print(pi) +print(f"pi to three decimal places is {pi:.3f}") +``` +```output +3.141592653589793 +pi to three decimal places is 3.142 +``` + +Or made to use scientific notation with an `e`: + +```python +print(1e9) +print(f"A billion in scientific notation is {1e9:.1e}") +``` +```output +1000000000.0 +A billion in scientific notation is 1.0e+09 +``` + +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). + +To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/). + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::: callout + ## Generative AI 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. @@ -207,6 +266,7 @@ To summarise the position, the recommendation is that you **avoid** getting help - loops - conditionals - string formatting +- avoid using generative AI during this course :::::::::::::::::::::::::::::::::::::::::::::::::: From 5d2eb86dc65d9a08d30aaf14c23de2a3ffef9998 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:46:20 +0100 Subject: [PATCH 13/18] removed keypoints changes to avoid clash with #77 --- episodes/01-introduction.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 490f85b..7091661 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -265,8 +265,6 @@ To summarise the position, the recommendation is that you **avoid** getting help - indexing - loops - conditionals -- string formatting -- avoid using generative AI during this course :::::::::::::::::::::::::::::::::::::::::::::::::: From d1ee44e550033612aa0d4ee8a66d47282f368ea7 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:52:16 +0100 Subject: [PATCH 14/18] fix: tried to fix markdown validation error --- episodes/01-introduction.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 7091661..c6cf20c 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -10,8 +10,6 @@ exercises: 0 :::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::: questions - - Python Refresher :::::::::::::::::::::::::::::::::::::::::::::::::: From 8d17825d60d50968792fe33e3843cbee82a983f3 Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:55:35 +0100 Subject: [PATCH 15/18] fix: removed callout heading for gen-AI section --- episodes/01-introduction.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index c6cf20c..94f84d9 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -244,8 +244,6 @@ To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/) :::::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::::: callout - ## Generative AI 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. From db5f898bd8cda09ce3ad20e3e1075db138b9fbcf Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 11:58:21 +0100 Subject: [PATCH 16/18] fix: readded questions tag --- episodes/01-introduction.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index 94f84d9..fc5bba3 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -10,6 +10,8 @@ exercises: 0 :::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::: questions + - Python Refresher :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -187,8 +189,6 @@ else: ::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::::: callout - ## Formatting Variables and Objects in Strings 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. @@ -244,6 +244,8 @@ To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/) :::::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::: callout + ## Generative AI 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. From e2249062c0bd4d73f59004ce867644dc66be2b3f Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 12:02:33 +0100 Subject: [PATCH 17/18] fix: reremoved callout tag --- episodes/01-introduction.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index fc5bba3..c862321 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -244,8 +244,6 @@ To learn more, see: [Python f-strings](https://realpython.com/python-f-strings/) :::::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::::: callout - ## Generative AI 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. From 0eca7c873353cbf512a9601636a4da69ff2ddf6b Mon Sep 17 00:00:00 2001 From: Scott Archer-Nicholls Date: Tue, 21 Apr 2026 12:08:37 +0100 Subject: [PATCH 18/18] fix: added callout section for f-strings --- episodes/01-introduction.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/episodes/01-introduction.md b/episodes/01-introduction.md index c862321..73260c8 100644 --- a/episodes/01-introduction.md +++ b/episodes/01-introduction.md @@ -189,6 +189,8 @@ else: ::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::: callout + ## Formatting Variables and Objects in Strings 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.