Skip to content
94 changes: 45 additions & 49 deletions 04_input_output.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
" - [Reading/Writing CSV files](#Reading/Writing-CSV-files)\n",
" - [Quiz on CSV](#Quiz-on-CSV)\n",
" - [Exercises](#Exercises)\n",
" - [Exercise 1: CSV to dictionary 🌶️](#Exercise-1:-CSV-to-dictionary-🌶️)\n",
" - [Exercise 2: Counting words 🌶️](#Exercise-2:-Counting-words-🌶️)\n",
" - [Exercise 3: Letter statistics 🌶️🌶️](#Exercise-3:-Letter-statistics-🌶️🌶️)\n",
" - [Exercise 4: Translating words 🌶️🌶️](#Exercise-4:-Translating-words-🌶️🌶️)\n",
" - [Exercise 5: Binary format 🌶️🌶️🌶️](#Exercise-5:-Binary-format-🌶️🌶️🌶️)"
" - [Exercise 1: CSV to dictionary (easy)](#Exercise-1:-CSV-to-dictionary-(easy))\n",
" - [Exercise 2: Counting words (easy)](#Exercise-2:-Counting-words-(easy))\n",
" - [Exercise 3: Letter statistics (medium)](#Exercise-3:-Letter-statistics-(medium))\n",
" - [Exercise 4: Translating words (medium)](#Exercise-4:-Translating-words-(medium))\n",
" - [Exercise 5: Binary format (hard)](#Exercise-5:-Binary-format-(hard))"
]
},
{
Expand Down Expand Up @@ -75,13 +75,7 @@
"- connecting to databases or other network services\n",
"\n",
"\n",
"The majority of these operations are covered by the Python standard library. We are going to see how to use them in this chapter.\n",
"\n",
"<div class=\"alert alert-block alert-info\">\n",
" <h4><b>Note</b></h4>\n",
"In reference to the chapter on functional programming, it is interesting to note that these functions perform <b>side-effects</b>. Therefore, any code containing these operations is no longer <b>pure</b> and is not referentially transparent. The same function can return different values for the same argument if called multiple times, and the function can have <b>long-distance</b> effects. That means they can modify the program state elsewhere, leading to unexpected results.<br><br>\n",
"Therefore, we suggest separating input and output from the other computations in your program. For example, if you have a complex calculation requiring several user inputs at several stages of the process, consider writing a function that only performs the calculation given all inputs and then requires all inputs separately, for example, through a single file. This makes your code easier to debug, test and understand.\n",
"</div>"
"The majority of these operations are covered by the Python standard library. We are going to see how to use them in this chapter."
]
},
{
Expand All @@ -108,8 +102,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"It is also possible to print any other python object using `print`. \n",
"In that case, the `__str__` **magic method** on that object's class is [called](https://docs.python.org/3/reference/datamodel.html#object.__str__)."
"It is also possible to print any other python object using `print`."
]
},
{
Expand Down Expand Up @@ -245,7 +238,7 @@
"metadata": {},
"outputs": [],
"source": [
"%%ipytest debug\n",
"%%ipytest\n",
"\n",
"def solution_print_odd(n: int) -> None: \n",
" \"\"\"Prints all odd numbers from 1 to n\n",
Expand All @@ -255,8 +248,7 @@
"\n",
" Returns:\n",
" - None (prints to console)\n",
" \"\"\"\n",
" pass"
" \"\"\""
]
},
{
Expand Down Expand Up @@ -287,7 +279,6 @@
" Returns:\n",
" - None (prints to console)\n",
" \"\"\"\n",
" pass\n",
"\n",
"solution_print_salutation()"
]
Expand Down Expand Up @@ -526,7 +517,7 @@
"metadata": {},
"source": [
"\n",
"1. Modify the function `solution_find_all_files` to find all files and directories in the [data](./tutorial/tests/data/) (./tutorial/tests/data/) directory and return them as a list of `Path` objects\n",
"1. Modify the function `solution_find_all_files` to find all files and directories in the ```/tutorial/tests/data``` directory and return them as a list of `Path` objects\n",
"\n",
"<div class=\"alert alert-block alert-info\">\n",
" <b>Hint:</b> The path to the data directory is available as the argument <code>current_path</code> of the function <code>solution_find_all_files</code>\n",
Expand Down Expand Up @@ -613,8 +604,7 @@
"\n",
" Returns:\n",
" - The number of directories in the directory\n",
" \"\"\"\n",
" pass\n"
" \"\"\""
]
},
{
Expand All @@ -627,9 +617,9 @@
"### Reading from a file\n",
"\n",
"We now want to learn how to read text from a file. \n",
"Let's see how to do this with an example: we want to open the file [hello.txt](./data/hello.txt) and read its contents.\n",
"Let's see how to do this with an example: we want to open the file [hello.txt](./tutorial/tests/data/hello.txt) and read its contents.\n",
"\n",
"1. The path is already identified, we know the file is in `./data/hello.txt`. We save this in a variable `path`.\n",
"1. The path is already identified, we know the file is in `./tutorial/tests/data/hello.txt`. We save this in a variable `path`.\n",
"2. We now can use the built-in function [`open`](https://docs.python.org/3/library/functions.html#open) to open the file. This function returns a [file object](https://docs.python.org/3/glossary.html#term-file-object) that we can use to further manipulate the file. To ensure we only open the file for reading, we pass the string \"r\" to the second argument of `open`.\n",
"3. Now we can read the contents using `read`, `readline` or `readlines`. `read` reads the whole file content into a single string, `readline` reads one line, while `readlines` reads the whole file content as a list of strings, one item per line in the file. This knowledge is useful when we only want to read part of a file or when the file is too big to fit in memory and we can only read parts.\n",
"4. Finally, we close the file using the `close` method on the file object.\n"
Expand Down Expand Up @@ -773,7 +763,7 @@
" Returns:\n",
" - A list of strings, each representing a line in the file\n",
" \"\"\"\n",
" pass"
" return"
]
},
{
Expand All @@ -787,7 +777,7 @@
"- We use `write` to write a *string* to the file. Other types of object should be converted to string before being written.\n",
"\n",
"\n",
"Let's see this in action by writing your name in a file called `me.txt` in [data](./data/)"
"Let's see this in action by writing your name in a file called `me.txt` in ```/tutorial/tests/data```"
]
},
{
Expand Down Expand Up @@ -902,26 +892,31 @@
"\n",
" Returns:\n",
" - None (writes to file)\n",
" \"\"\"\n",
" pass"
" \"\"\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"2. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending**, `length` is **number of characters** in that line **without the line separator**.\n",
"If `input_file` contains these lines:\n",
"2. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending (\\r\\n)**, `length` is **number of characters** in that line. The characters are added automatically by the operating system when reading a file. Windows uses **\\r\\n** whereas Linux and MacOS use only **\\n**. To remove the line ending characters, use ```strip(\"\\r\\n\")```, e.g.: ```line.strip(\"\\r\\n\")```.\n",
"\n",
" If `input_file` contains these lines:\n",
" \n",
" ```\n",
" first\n",
" second\n",
" ```\n",
" \n",
" we expect the output file to contain these lines:\n",
" \n",
" ```\n",
" first, 5\n",
" second, 6\n",
" ```"
" ```\n",
" \n",
" Do not forget to add a **\\n** when writing lines in the file."
]
},
{
Expand All @@ -945,8 +940,7 @@
"\n",
" Returns:\n",
" - None (writes to file)\n",
" \"\"\"\n",
" pass"
" \"\"\""
]
},
{
Expand Down Expand Up @@ -1201,7 +1195,9 @@
"source": [
"message = \"Ciao\"\n",
"message_secret = bytes(message, \"utf-8\")\n",
"[print(f\"The `uft8` codepoint is = {enc}, the bytes representation = {enc.to_bytes(4, 'little')}, the representation is {chr(enc)}\") for plain, enc in zip(message, message_secret)]"
"print_messages = [f\"The `uft8` codepoint is = {enc}, the bytes representation = {enc.to_bytes(4, 'little')}, the representation is {chr(enc)}\" for plain, enc in zip(message, message_secret)]\n",
"for msg in print_messages:\n",
" print(msg)"
]
},
{
Expand All @@ -1225,7 +1221,7 @@
"These packages are outside of the scope of this tutorial and will not be covered here.\n",
"\n",
"\n",
"Let's see how to read csv files using `csv` with an example by reading [example.csv](./data/example.csv):"
"Let's see how to read csv files using `csv` with an example by reading [example.csv](./tutorial/tests/data/example.csv):"
]
},
{
Expand Down Expand Up @@ -1330,7 +1326,7 @@
"tags": []
},
"source": [
"### Exercise 1: CSV to dictionary 🌶️"
"### Exercise 1: CSV to dictionary (easy)"
]
},
{
Expand Down Expand Up @@ -1404,7 +1400,7 @@
" Returns:\n",
" - A dictionary with each row represented as a key, value pair\n",
" \"\"\"\n",
" pass"
" return"
]
},
{
Expand All @@ -1414,7 +1410,7 @@
"tags": []
},
"source": [
"### Exercise 2: Counting words 🌶️"
"### Exercise 2: Counting words (easy)"
]
},
{
Expand Down Expand Up @@ -1472,7 +1468,7 @@
" Returns:\n",
" - The number of words in the file\n",
" \"\"\"\n",
" pass"
" return"
]
},
{
Expand All @@ -1482,7 +1478,7 @@
"tags": []
},
"source": [
"### Exercise 3: Letter statistics 🌶️🌶️"
"### Exercise 3: Letter statistics (medium)"
]
},
{
Expand Down Expand Up @@ -1522,7 +1518,7 @@
"metadata": {},
"outputs": [],
"source": [
"%%ipytest input_output\n",
"%%ipytest\n",
"\n",
"import pathlib as pl\n",
"import string\n",
Expand All @@ -1538,7 +1534,7 @@
" Returns:\n",
" - A dictionary with a count of each letter\n",
" \"\"\"\n",
" pass"
" return"
]
},
{
Expand All @@ -1548,7 +1544,7 @@
"tags": []
},
"source": [
"### Exercise 4: Translating words 🌶️🌶️"
"### Exercise 4: Translating words (medium)"
]
},
{
Expand All @@ -1558,7 +1554,7 @@
"tags": []
},
"source": [
"Write a function which takes the words from the file `english.txt` and translates them to Italian using the dictionary file `dict.csv`. The output should be a **list of tuples** with the pair `italian, english` if the word is found and nothing otherwise.\n",
"Write a function which takes the words from the file `english.txt` and translates them to Italian using the dictionary file `dict.csv`. The output should be a **list of tuples** with the pair `italian, english` **if the word is found and nothing otherwise**.\n",
"\n",
"For example, given the `english.txt` file:\n",
"\n",
Expand Down Expand Up @@ -1600,6 +1596,7 @@
"source": [
"%%ipytest\n",
"\n",
"import csv\n",
"import pathlib as pl\n",
"\n",
"def solution_exercise4(english: pl.Path, dictionary: pl.Path) -> list[(str, str)]:\n",
Expand All @@ -1615,8 +1612,7 @@
" Returns:\n",
" - A list of tuples with the english / italian words\n",
" \"\"\"\n",
"\n",
" pass"
" return"
]
},
{
Expand All @@ -1626,7 +1622,7 @@
"tags": []
},
"source": [
"### Exercise 5: Binary format 🌶️🌶️🌶️"
"### Exercise 5: Binary format (hard)"
]
},
{
Expand Down Expand Up @@ -1678,14 +1674,14 @@
" Returns:\n",
" - The secret message\n",
" \"\"\"\n",
" pass"
" return"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand All @@ -1699,7 +1695,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
"version": "3.13.5"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion 05_object_oriented_programming.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
"version": "3.13.5"
}
},
"nbformat": 4,
Expand Down
8 changes: 4 additions & 4 deletions tutorial/quiz/input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, title=""):
question="What happens if you call <code>input()</code> in the middle of a function?",
options={
"The function execution stops and it waits for the user to type an input": "Correct! Input is a blocking function which waits for user to enter a string in the console and press enter.",
"The function continues its execution": "Wrong!",
"The function continues its execution": "Wrong! Input is a blocking function which waits for user input.",
},
correct_answer="The function execution stops and it waits for the user to type an input",
shuffle=True,
Expand All @@ -57,7 +57,7 @@ def __init__(self, title=""):
q1 = Question(
question="What does the operator <code>/</code> do when applied to two <code>Pathlib.Path</code> objects?",
options={
"It removes the second path from the first": "Wrong, try it in the shell.",
"It removes the second path from the first": "Wrong, try it in a cell below.",
"It concatenates paths": "Correct, it lets you construct a path from different segments",
},
correct_answer="It concatenates paths",
Expand All @@ -68,7 +68,7 @@ def __init__(self, title=""):
question="If you use Pathlib, do you need to use different path separators on Windows and Linux to combine path segments?",
options={
"No, you can combine Pathlib.Path objects with /": "Correct! Pathlib will then generate the correct path for your OS.",
"Yes": "Wrong! You can always use <code>/</code>",
"Yes": "Wrong! You can always use <code>/</code>",
},
correct_answer="No, you can combine Pathlib.Path objects with /",
shuffle=True,
Expand All @@ -78,7 +78,7 @@ def __init__(self, title=""):
question="""The path </code>Pathlib.Path("./")</code> represent a relative path. What location does it refer to?""",
options={
"Relative to the current working directory, the location of the current Python script being run": "Correct!",
"Relative to the user's home directory": "Wrong!",
"Relative to the user's home directory": "Wrong! It is relative to the current working directory.",
},
correct_answer="Relative to the current working directory, the location of the current Python script being run",
shuffle=True,
Expand Down
24 changes: 24 additions & 0 deletions tutorial/tests/data/example1.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<<<<<<< HEAD
this,is,data
0,1,2
1,2,3
2,3,4
3,4,5
4,5,6
5,6,7
6,7,8
7,8,9
8,9,10
=======
this,is,data
0,1,2
1,2,3
2,3,4
3,4,5
4,5,6
5,6,7
6,7,8
7,8,9
8,9,10
>>>>>>> 5bd589eb6742c15e877451b291ee8d04a405d4b1
9,10,11
1 change: 1 addition & 0 deletions tutorial/tests/data/me.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Simone
Loading