Skip to content
37 changes: 36 additions & 1 deletion index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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
:::
Expand All @@ -82,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}
Expand Down
21 changes: 18 additions & 3 deletions slides/basics.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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
:::
Expand Down Expand Up @@ -159,6 +159,7 @@ print(1 + 2.1)
::: {.fragment .fade-in}
* What about an **int** and a **str**?
<br/>

```{python}
#| echo: true
#| output-location: fragment
Expand Down Expand Up @@ -298,11 +299,21 @@ my_tuple = (1, 2.0, 'cat', 'dog')

print(type(my_tuple))
print(my_tuple[2])

my_tuple[2] = 'rabbit'
```
::::
:::

<br/>

:::: {.fragment .fade-in}
```{python}
#| echo: true
#| output-location: fragment
#| error: true
my_tuple[2] = 'new_element'
print(my_tuple)
```
::::
:::::

## Unpacking {.smaller}
Expand Down Expand Up @@ -479,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}
Expand Down
12 changes: 10 additions & 2 deletions slides/classes_and_objects.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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()
```
:::::
:::
Expand All @@ -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)

Expand Down
18 changes: 18 additions & 0 deletions slides/errors_and_exceptions.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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?

Expand Down
7 changes: 1 addition & 6 deletions slides/first_script.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@
* `Scripts` (.py)
:::

::: {.fragment .fade-in}
Demo time! 🧑🏻‍💻👩🏻‍💻
:::



## Writing your first Python script

Expand All @@ -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"}
:::
35 changes: 26 additions & 9 deletions slides/functions.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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
:::
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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}
Expand All @@ -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
:::

:::
Expand Down
2 changes: 1 addition & 1 deletion slides/interactive_python.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ Demo time! 🧑🏻‍💻👩🏻‍💻
:::

::: {.fragment .fade-in}
![](/img/interactive_python.png){width=80%}
![](/img/interactive_python.png){width=70% fig-align="center"}
:::

13 changes: 7 additions & 6 deletions slides/loading_and_saving.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
```

15 changes: 2 additions & 13 deletions slides/virtual_environments.qmd
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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}

Expand Down Expand Up @@ -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):
Expand Down