Skip to content

Commit

Permalink
fix(ci): htmlproofer fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
lwasser committed Oct 4, 2024
1 parent fc327a3 commit 2213503
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 33 deletions.
12 changes: 12 additions & 0 deletions _static/matomo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Matomo analytics
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://pyopensci.matomo.cloud/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src='//cdn.matomo.cloud/pyopensci.matomo.cloud/matomo.js'; s.parentNode.insertBefore(g,s);
})();
58 changes: 27 additions & 31 deletions clean-modular-code/python-functions.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
title: "Introduction to Writing Functions in Python"
excerpt: "A function is a reusable block of code that performs a specific task. Learn how to use functions to write DRY (Do Not Repeat Yourself) code in Python."
authors: ['Leah Wasser','Jenny Palomino']
jupyter:
jupytext:
formats: ipynb,md
Expand All @@ -16,61 +15,62 @@ jupyter:
name: python3
---

<!-- #region editable=true slideshow={"slide_type": ""} -->
# Write Efficient Modular Code Using Functions

Three strategies for eliminating repetition and improving the efficiency of your code:
Three strategies for eliminating repetition and improving the efficiency of your code:

1. loops,
2. conditional statements, and
3. functions.
1. loops,
2. conditional statements, and
3. functions.

Here you will learn how writing functions in **Python** can help you to execute a specific task while also making your code more maintainable.

A function is a reusable block of code that performs a specific task. Functions receive inputs to which code is applied and return outputs (or results) of the code.
A function is a reusable block of code that performs a specific task. Functions receive inputs to which code is applied and return outputs (or results) of the code.

`input parameter –> function does something –> output results`

For example:
<!-- #endregion -->

```python
```python editable=true slideshow={"slide_type": ""}
x = 5
# The print statement is a function that provides output.
print(x)
```

<!-- #region -->
Functions can help you to both eliminate repetition and improve efficiency in your code through modularity.
<!-- #region editable=true slideshow={"slide_type": ""} -->
Functions can help you to both eliminate repetition and improve efficiency in your code through modularity.

Modularity means that code is separated into independent units that can be reused and even be combined to complete a longer chain of tasks.
Modularity means that code is separated into independent units that can be reused and even be combined to complete a longer chain of tasks.

<figure>
<a href="/images/clean-code/write-functions-for-all-things.png">
<img src="{{ site.url }}/images/earth-analytics/clean-code/write-functions-for-all-things.png" alt="You can implement strategies such as loops and functions in your code to replace tasks that you are performing over and over. Source: Francois Michonneau."></a>
<figcaption> You can implement strategies such as loops and functions in your code to replace tasks that you are performing over and over. Source: Francois Michonneau.
</figcaption>
</figure>
:::{figure} /images/clean-code/functions-for-all-things.png
:alt: You can implement strategies such as loops and functions in your code to replace tasks that you are performing over and over. Source: Francois Michonneau.
:target: /images/clean-code/write-functions-for-all-things.png

You can use loops and functions in your code to replace repeating tasks.
Source: Francois Michonneau.
:::

## The Benefits of Functions

* Modularity: Functions only need to be defined once in a workflow. Functions that you write for specific tasks can be used over and over, without needing to redefine the function again. A function that you write for one **Python** workflow can also be reused in other workflows especially if you make your code installable.

* Fewer variables: When you run a function, the intermediate variables (i.e. placeholders) that it creates are not stored as explicit variables unless you specify otherwise. This saves memory and keeps your **Python** environment cleaner.
* Fewer variables: When you run a function, the intermediate variables (i.e. placeholders) that it creates are not stored as explicit variables unless you specify otherwise. This saves memory and keeps your **Python** environment cleaner.

* Better documentation: Well-documented functions help other users understand the steps of your processing and helps your future self to understand previously written code.

* Easier to maintain and edit your code: Because a function is only defined once in the workflow, you can simply just update the original function definition. Then, each instance in which you call that function in your code (i.e. when same task is performed) is automatically updated.

* Tests & checks: Writing functions allows you you to your code to handle issues and edge cases in your code. It also can make it easier to write tests for your code.


### Write Modular Functions and Code

A well-defined function only does one thing, but it does it well and often in various contexts. Often, the operations contained in a good function are generally useful for many tasks.
A well-defined function only does one thing, but it does it well and often in various contexts. Often, the operations contained in a good function are generally useful for many tasks.

Take, for instance, the **numpy** function called `mean()`, which computes mean values from a **numpy** array.

This function only does one thing (i.e. computes a mean); however, you may use the `np.mean()` function many times in your code on multiple **numpy** arrays because it has been defined to take any **numpy** array as an input.
This function only does one thing (i.e. computes a mean); however, you may use the `np.mean()` function many times in your code on multiple **numpy** arrays because it has been defined to take any **numpy** array as an input.

For example:
<!-- #endregion -->
Expand All @@ -83,62 +83,58 @@ arr = np.array([1, 2, 3])
np.mean(arr)
```

<!-- #region -->
<!-- #region editable=true slideshow={"slide_type": ""} -->
The `np.mean()` function is modular, and it can be easily combined with other functions to accomplish a variety of tasks.

When you write modular functions, you can reuse them for other workflows and projects. Some people even write their own **Python** packages for personal and professional use that contain custom functions for tasks that they have to complete regularly.

### Functions Create Fewer Variables

When you code tasks line by line, you often create numerous intermediate variables that you do not need to use again.
When you code tasks line by line, you often create numerous intermediate variables that you do not need to use again.

This is inefficient and can cause your code to be repetitive, if you are constantly creating variables that you will not use again.
This is inefficient and can cause your code to be repetitive, if you are constantly creating variables that you will not use again.

Functions allow you to focus on the inputs and the outputs of your workflow, rather than the intermediate steps, such as creating extra variables that are not needed.


## Reasons Why Functions Improve Code Readability

### Functions Can Result in Better Documentation

Ideally, your code is easy to understand and is well-documented with **Python** comments (and **Markdown** in **Jupyter Notebook**). However, what might seem clear to you now might not be clear 6 months from now, or even 3 weeks from now.

Well-written functions help you document your workflow because:

* They are well-documented by clearly outlining the inputs and outputs.
* They use descriptive names that help you better understand the task that the function performs.


### Expressive Function Names Make Code Self-Describing

When writing your own functions, you should name functions using verbs and/or clear labels to indicate what the function does (i.e. `in_to_mm` for converting inches to millimeters).
When writing your own functions, you should name functions using verbs and/or clear labels to indicate what the function does (i.e. `in_to_mm` for converting inches to millimeters).

This makes your code more expressive (or self-describing), and in turn, makes it easier to read for you, your future self, and your colleagues.


### Modular Code is Easier to Maintain and Edit

If all your code is written line by line (with repeated code in multiple parts of your document) it can be challenging to maintain and edit.

Imagine having to fix one element of a line of code that is repeated many times. You will have to find and replace that code to implement the fix in EVERY INSTANCE it occurs in your code!

You may also be duplicating your comments where you duplicate parts of your code. So how do you keep the duplicated comments in sync?
You may also be duplicating your comments where you duplicate parts of your code. So how do you keep the duplicated comments in sync?

A comment that is misleading because the code changed is actually worse than no comment at all.

Organizing your code using functions from the beginning allows you to explicitly document the tasks that your code performs, as all code and documentation for the function is contained in the function definition.


### You Can Incorporate Testing To Ensure Code Runs Properly

While you will not learn about testing in this chapter, note that functions are also very useful for testing.
While you will not learn about testing in this chapter, note that functions are also very useful for testing.

As your code gets longer and more complex, it is more prone to mistakes. For example, if your analysis relies on data that gets updated often, you may want to make sure that all the columns in your spreadsheet are present before performing an analysis. Or, that the new data are not formatted in a different way.

Changes in data structure and format could cause your code to not run. Or, in the worse case scenario, your code may run but return the wrong values!

If all your code is made up of functions (with built-in tests to ensure that they run as expected), then you can control the input to the function and test that the output returned is correct for that input. It is something that would be difficult to do if all of your code is written line by line with repeated steps.


## Summary of Writing Modular Code with Functions

It is a good idea to learn how to:
Expand Down
3 changes: 1 addition & 2 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,9 @@
".DS_Store",
".github",
".nox",
"README.md",
"**/README.md",
"styles/write-good/README.md",
"styles/*",
".pytest_cache/README.md",
"vale-styles/*",
"CODE_OF_CONDUCT.md",
"**/data/**",
Expand Down
Binary file added images/clean-code/functions-for-all-things.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2213503

Please sign in to comment.