From c96af262cee44e3877aae09288009c424c646c1e Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:01:03 +0100 Subject: [PATCH 01/11] No scrolling on REPL slide --- slides/interactive_python.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slides/interactive_python.qmd b/slides/interactive_python.qmd index 9c143f6..ebbd283 100644 --- a/slides/interactive_python.qmd +++ b/slides/interactive_python.qmd @@ -15,6 +15,6 @@ Demo time! πŸ§‘πŸ»β€πŸ’»πŸ‘©πŸ»β€πŸ’» ::: ::: {.fragment .fade-in} -![](/img/interactive_python.png){width=80%} +![](/img/interactive_python.png){width=70% fig-align="center"} ::: From 0924cf7b847493007f00fcb96b5ba923eea1adcb Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:03:31 +0100 Subject: [PATCH 02/11] Remove extra animation in data types slide --- slides/basics.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slides/basics.qmd b/slides/basics.qmd index 5ae84ca..f343490 100644 --- a/slides/basics.qmd +++ b/slides/basics.qmd @@ -51,7 +51,7 @@ print(y) ``` ## Data types -::: {.fragment .incremental .smaller} +::: {.incremental style="font-size: 80%;"} * Different kinds of data are stored in different ways in memory * You can use the `type()` function to find out what type of data a variable contains ::: From 452246198742abeb70caf1addb5bb3c70c80c755 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:08:44 +0100 Subject: [PATCH 03/11] Move tuple immutability example out of columns --- slides/basics.qmd | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/slides/basics.qmd b/slides/basics.qmd index f343490..4fba5ec 100644 --- a/slides/basics.qmd +++ b/slides/basics.qmd @@ -159,6 +159,7 @@ print(1 + 2.1) ::: {.fragment .fade-in} * What about an **int** and a **str**?
+ ```{python} #| echo: true #| output-location: fragment @@ -298,11 +299,21 @@ my_tuple = (1, 2.0, 'cat', 'dog') print(type(my_tuple)) print(my_tuple[2]) - -my_tuple[2] = 'rabbit' ``` :::: ::: + +
+ +:::: {.fragment .fade-in} +```{python} +#| echo: true +#| output-location: fragment +#| error: true +my_tuple[2] = 'new_element' +print(my_tuple) +``` +:::: ::::: ## Unpacking {.smaller} From 8d2dcd8719b88afbc42444454a412764ec346e23 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:18:35 +0100 Subject: [PATCH 04/11] Add information about range --- slides/basics.qmd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/slides/basics.qmd b/slides/basics.qmd index 4fba5ec..41e8e1f 100644 --- a/slides/basics.qmd +++ b/slides/basics.qmd @@ -490,6 +490,10 @@ for i in range(5): * You can loop over any iterable * Use `_` if you don't need the loop variable * `enumerate()` gives you the index and the value +* `range()` generates a sequence of numbers + + `range(n)` from 0 to n-1 + + `range(a, b)` from a to b-1 + + `range(a, b, step)` from a to b-1 with jumps of step ::: ::: {.column width="45%"} :::: {.fragment .fade-in} From 89dd056b3e9f622c58587a29cb6b74a04adcdb7b Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:18:54 +0100 Subject: [PATCH 05/11] Center the screenshot for first script --- slides/first_script.qmd | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/slides/first_script.qmd b/slides/first_script.qmd index c99fc28..60672f2 100644 --- a/slides/first_script.qmd +++ b/slides/first_script.qmd @@ -6,11 +6,6 @@ * `Scripts` (.py) ::: -::: {.fragment .fade-in} -Demo time! πŸ§‘πŸ»β€πŸ’»πŸ‘©πŸ»β€πŸ’» -::: - - ## Writing your first Python script @@ -19,5 +14,5 @@ Demo time! πŸ§‘πŸ»β€πŸ’»πŸ‘©πŸ»β€πŸ’» ::: ::: {.fragment .fade-in} -![](/img/your_first_script.png){width=70%} +![](/img/your_first_script.png){width=70% fig-align="center"} ::: \ No newline at end of file From ab3f85763ea551b0f2515c068ea2d1c846f0b797 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:22:13 +0100 Subject: [PATCH 06/11] Make small edits to csv demo --- slides/loading_and_saving.qmd | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/slides/loading_and_saving.qmd b/slides/loading_and_saving.qmd index 7dcec8f..73b41e5 100644 --- a/slides/loading_and_saving.qmd +++ b/slides/loading_and_saving.qmd @@ -60,7 +60,7 @@ print(contents) ::::: ## Demo -* Write a script that saves the below data to a comma-separated file +* Let's write a script that saves the below data to a comma-separated file ```{python} #| echo: true @@ -71,16 +71,17 @@ samples = [(0, 12, 53), (1, 7, 23), (2, 15, 30)] ## Demo ```{python} #| echo: true +#| code-line-numbers: "|4|5,6|8|9,10|8,11|" column_labels = "sample_id,speed,distance" samples = [(0, 12, 53), (1, 7, 23), (2, 15, 30)] -with open("out.csv", "w") as file: - file.write(column_labels) - file.write("\n") +with open("out.csv", "w") as data_file: + data_file.write(column_labels) + data_file.write("\n") for sample in samples: for value in sample: - file.write(str(value) + ",") - file.write("\n") + data_file.write(str(value) + ",") + data_file.write("\n") ``` From 1c63df63a1896e378afe82801171250833f5a29b Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:24:00 +0100 Subject: [PATCH 07/11] Update schedule --- index.qmd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.qmd b/index.qmd index 06d0966..a29a8c2 100644 --- a/index.qmd +++ b/index.qmd @@ -60,10 +60,12 @@ format: ## Schedule {.smaller} ::: {.incremental} * Recap and Q&A -* Using third party libraries from pip and conda * Functions and methods * Classes and objects * Errors and exceptions +* Integrated Development Environments (IDEs) +* Virtual environments +* Modules and packages * Organising your code * Documenting your code ::: From 6885c3a7938debbc380704da5fa4e8f1d0927ae9 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:25:02 +0100 Subject: [PATCH 08/11] Change indentation in functions.qmd --- slides/functions.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slides/functions.qmd b/slides/functions.qmd index 626dc57..91de5d7 100644 --- a/slides/functions.qmd +++ b/slides/functions.qmd @@ -53,7 +53,7 @@ print(y) * Functions allow you to: + Reuse code + Break problems into smaller pieces - + Scope defined by indentation +* Scope defined by indentation * Defined using the `def` keyword * Can take inputs (arguments) and return outputs ::: From 750a88923a9aaea774231d8b948f9135d90f8532 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:59:33 +0100 Subject: [PATCH 09/11] Small edits in functions --- slides/functions.qmd | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/slides/functions.qmd b/slides/functions.qmd index 91de5d7..15ed1a4 100644 --- a/slides/functions.qmd +++ b/slides/functions.qmd @@ -101,6 +101,7 @@ def is_valid_password(password): ```{python} #| echo: true #| output-location: fragment +#| code-line-numbers: "|1|2,3|4,5|" def is_valid_password(password): if len(password) >= 8: return True @@ -215,7 +216,7 @@ def longer_string(str1, str2=""): ```{python} #| echo: true #| output-location: fragment -#| code-line-numbers: "|1|2,4|" +#| code-line-numbers: "|1|2,3|4,5|7|" def longer_string(str1, str2=""): if len(str1) > len(str2): @@ -225,8 +226,8 @@ def longer_string(str1, str2=""): print(long_str) -print(longer_string("apple", "banana")) -print(longer_string("apple")) +longer_string("apple", "banana") +longer_string("apple") ``` ## Using `*` and `**` {.smaller} @@ -241,26 +242,42 @@ print(longer_string("apple")) ```{python} #| echo: true #| output-location: fragment +#| code-line-numbers: "|1|2,3|5,6|8,9|11,12|" def my_func(*args, **kwargs): - print(f"Unpacking list: {args}") - print(f"Unpacking dictionary: {kwargs}") + print(f"Unpacking positional arguments: {args}") + print(f"Unpacking keyword arguments: {kwargs}") my_list = [1, 2, 3, 4, 5] my_dict = {'a': 1, 'b': 2, 'c': 3} -print("Unpacking list:") my_func(*my_list) -print("Unpacking dictionary:") my_func(**my_dict) ``` ::: +## Using `*` and `**` {.smaller} + +::: {.fragment .fade-in} +```{python} +#| echo: true +#| output-location: fragment +def my_func(*args, **kwargs): + print(f"Unpacking positional arguments: {args}") + print(f"Unpacking keyword arguments: {kwargs}") + +my_func(1, 'a', 3.14) +my_func(name="John", age=30) +my_func(1, 2, 3, name="Jane", city="New York") +``` +::: + ## How are `*args` and `**kwargs` useful? {.smaller} :::: {.columns} ::: {.column width="55%"} ::: {.incremental .smaller} -* `*args` and `**kwargs` are useful when you don't know how many arguments will be passed to the function +* `*args` and `**kwargs` are useful when you don't know which arguments will be passed to the function +* Or when you wrap another function and want to pass all arguments to the wrapped function ::: ::: From ef4cd2f9d2cb5b03ad6ce4191212995c232b0cd6 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 18:59:50 +0100 Subject: [PATCH 10/11] Update classes and objects example --- slides/classes_and_objects.qmd | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/slides/classes_and_objects.qmd b/slides/classes_and_objects.qmd index 45b2e79..40f2377 100644 --- a/slides/classes_and_objects.qmd +++ b/slides/classes_and_objects.qmd @@ -44,14 +44,19 @@ file_obj.close() ```{python} #| echo: true #| output-location: fragment -#| code-line-numbers: "|1|2,3|5|6|" +#| code-line-numbers: "|1|2,3|5,6|8,9|10|11|" class Animal(): def __init__(self, species): self.species = species + def greet(self): + print(f"Hello, I am a {self.species}.") + pingu = Animal("penguin") +print(type(pingu)) print(pingu.species) +pingu.greet() ``` ::::: ::: @@ -73,13 +78,16 @@ pingu.make_noise() # Output: noot ```{python} #| echo: true #| output-location: fragment -#| code-line-numbers: "|2|2,4|6,7|" +#| code-line-numbers: "|2|2,4|9,10|" class Animal(): def __init__(self, species, noise): self.species = species self.noise = noise + def greet(self): + print(f"{self.noise}, I am a {self.species}.") + def make_noise(self): print(self.noise) From b15362923a7ff02e799ac71df5d3bcabf5371e26 Mon Sep 17 00:00:00 2001 From: IgorTatarnikov Date: Mon, 29 Sep 2025 19:23:03 +0100 Subject: [PATCH 11/11] Move installation slides, change the virtual environments slides --- index.qmd | 33 ++++++++++++++++++++++++++++++++ slides/errors_and_exceptions.qmd | 18 +++++++++++++++++ slides/virtual_environments.qmd | 15 ++------------- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/index.qmd b/index.qmd index a29a8c2..de9f2d3 100644 --- a/index.qmd +++ b/index.qmd @@ -84,6 +84,39 @@ format: Please ask any **questions at any time**! ::: +# Installation + +## Install miniforge {.smaller} + +[Click here to go to the download page](https://conda-forge.org/download/) + + +Add Miniforge to PATH when prompted during installation. + +![](img/miniforge_window_add_to_path.png){width="25%" fig-align="center"} + +Try the below in either your terminal (Mac/Linux) or Miniconda Prompt (Windows): +```bash +conda --version +``` + +::: {.callout-caution collapse="true"} +## Windows troubleshooting +- Did you had a previous version of Anaconda installed? You might need to uninstall it first. +- `conda not found`? Run `conda init` in your terminal. +::: + +## Install an IDE {.smaller} + +::: {.fragment .fade-in} +* [Visual Studio Code](https://code.visualstudio.com/download) - customisable, extensible, open source +* [PyCharm](https://www.jetbrains.com/pycharm/download/) - opinionated defaults, not fully free (free for educational use) +::: + +## Install a text editor (macOS) {.smaller} +* [Sublime Text](https://www.sublimetext.com/) - lightweight text editor +* Windows can use the built-in Notepad or [Notepad++](https://notepad-plus-plus.org/downloads/) + # Why learn Python? ## Why learn Python? {.smaller} diff --git a/slides/errors_and_exceptions.qmd b/slides/errors_and_exceptions.qmd index 22a1b3d..b2bd0c7 100644 --- a/slides/errors_and_exceptions.qmd +++ b/slides/errors_and_exceptions.qmd @@ -94,10 +94,12 @@ a_list[5] :::: ## Tracebacks {.smaller} +::: {.incremental} * Help you find the source of the error * Read from the bottom up * Look for the last line that is *your* code * [Debugging manifesto](https://wizardzines.com/images/debugging-manifesto.pdf) :bug: +::: ## Tracebacks {.smaller} ```{python} @@ -115,6 +117,22 @@ def call_func(x): z = call_func(10) ``` +## Tracebacks {.smaller} +```{python} +#| echo: true +#| output-location: fragment +#| error: true + +def none_function(): + return None + +def get_file_name(): + return none_function() + +file_name = none_function() +open_file = open(file_name) +``` + ## Handling exceptions {.smaller} * What if you know an error might happen? diff --git a/slides/virtual_environments.qmd b/slides/virtual_environments.qmd index dfef719..06bcaf4 100644 --- a/slides/virtual_environments.qmd +++ b/slides/virtual_environments.qmd @@ -1,5 +1,5 @@ ## Scientific Python ecosystem {.smaller} -![Diagram showing the scientific Python ecosystem.](/img/python-ecosystem.png) +![](/img/python-ecosystem.png){alt="Scientific Python ecosystem"} ::: footer [Aaron Meurer, β€˜Python Array API Standard’, SciPy 2023](https://www.youtube.com/watch?v=16rB-fosAWw) @@ -17,7 +17,7 @@ ## Virtual environments {.smaller} -![[Comic from xkcd](https://xkcd.com/1987/)](https://imgs.xkcd.com/comics/python_environment.png){width="20%"} +![[](https://xkcd.com/1987/)](https://imgs.xkcd.com/comics/python_environment.png){width="20%" alt="xkcd comic about Python environments"} ## Virtual environments {.smaller} @@ -59,17 +59,6 @@ - Future you (HPC, etc...) ::: -## Install miniforge - -[Click here to go to the download page](https://conda-forge.org/download/) - -::: {.callout-caution collapse="true"} -## Windows troubleshooting -- Did you had a previous version of Anaconda installed? You might need to uninstall it first. -- ![Remember to add Miniforge to your PATH! The installer will say is not required, but it is!](img/miniforge_window_add_to_path.png){width="25%"} -- `conda not found`? Run `conda init` in your terminal. -::: - ## Environment management In your terminal (use Anaconda Prompt on Windows):