From dccccd249c34be6f2fb4b0c4f49b5357d4c52027 Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <MichielCottaar@protonmail.com> Date: Mon, 9 Mar 2020 15:01:18 +0000 Subject: [PATCH] Clarifications and added f'{a=}' to second practical --- getting_started/02_text_io.ipynb | 75 +++++++++++++++++++++++++------- getting_started/02_text_io.md | 52 +++++++++++++++------- 2 files changed, 95 insertions(+), 32 deletions(-) diff --git a/getting_started/02_text_io.ipynb b/getting_started/02_text_io.ipynb index 310b3ad..d0be258 100644 --- a/getting_started/02_text_io.ipynb +++ b/getting_started/02_text_io.ipynb @@ -45,15 +45,15 @@ "source": [ "* [Reading/writing files](#reading-writing-files)\n", "* [Creating new strings](#creating-new-strings)\n", - " * [String syntax](#string-syntax)\n", - " * [Unicode versus bytes](#unicode-versus-bytes)\n", - " * [Converting objects into strings](#converting-objects-into-strings)\n", - " * [Combining strings](#combining-strings)\n", - " * [String formattings](#string-formatting)\n", + " * [String syntax](#string-syntax)\n", + " * [Unicode versus bytes](#unicode-versus-bytes)\n", + " * [Converting objects into strings](#converting-objects-into-strings)\n", + " * [Combining strings](#combining-strings)\n", + " * [String formattings](#string-formatting)\n", "* [Extracting information from strings](#extracting-information-from-strings)\n", - " * [Splitting strings](#splitting-strings)\n", - " * [Converting strings to numbers](#converting-strings-to-numbers)\n", - " * [Regular expressions](#regular-expressions)\n", + " * [Splitting strings](#splitting-strings)\n", + " * [Converting strings to numbers](#converting-strings-to-numbers)\n", + " * [Regular expressions](#regular-expressions)\n", "* [Exercises](#exercises)\n", "\n", "<a class=\"anchor\" id=\"reading-writing-files\"></a>\n", @@ -67,7 +67,8 @@ "\n", "* `mode` is one of `'r'` (for read-only access), `'w'` (for writing a file,\n", " this wipes out any existing content), `'a'` (for appending to an existing\n", - " file).\n", + " file). A `'b'` can be added to any of these to open the file in \"byte\"-mode,\n", + " which prevents python from interpreting non-text (e.g., NIFTI) files as text.\n", "\n", "* `file_object` is a variable name which will be used within the `block of\n", " code` to access the opened file.\n", @@ -111,7 +112,7 @@ " # each line is returned with its\n", " # newline character still intact,\n", " # so we use rstrip() to remove it.\n", - " print('{}: {}'.format(i, line.rstrip()))\n", + " print(f'{i}: {line.rstrip()}'))\n", " if i == 4:\n", " break" ] @@ -120,6 +121,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "> enumerate takes any sequence and returns 2-element tuples with the index and the sequence item\n", + "\n", "A very similar syntax is used to write files:" ] }, @@ -138,7 +141,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that no new line characters get added automatically. We can investigate\n", + "Note that new line characters do not get added automatically. We can investigate\n", "the resulting file using" ] }, @@ -243,6 +246,23 @@ "print(a_string)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can even include unicode characters:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_string = \"Python = ðŸ\"\n", + "print(a_string)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -300,6 +320,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "> This will lead to a syntax warning in python 3.8 or greater\n", + "\n", "<a class=\"anchor\" id=\"unicode-versus-bytes\"></a>\n", "#### unicode versus bytes\n", "\n", @@ -403,7 +425,7 @@ "\n", "\n", "<a class=\"anchor\" id=\"converting-objects-into-strings\"></a>\n", - "### converting objects into strings\n", + "### Converting objects into strings\n", "\n", "There are two functions to convert python objects into strings, `repr()` and\n", "`str()`. All other functions that rely on string-representations of python\n", @@ -529,9 +551,9 @@ "<a class=\"anchor\" id=\"string-formatting\"></a>\n", "### String formatting\n", "Using the techniques in [Combining strings](#combining-strings) we can build simple strings. For longer strings it is often useful to first write a template strings with some placeholders, where variables are later inserted. Built into python are currently 4 different ways of doing this (with many packages providing similar capabilities):\n", - "* the recommended [new-style formatting](https://docs.python.org/3/library/string.html#format-string-syntax).\n", - "* printf-like [old-style formatting](https://docs.python.org/3/library/stdtypes.html#old-string-formatting)\n", "* [formatted string literals](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) (these are only available in python 3.6+)\n", + "* [new-style formatting](https://docs.python.org/3/library/string.html#format-string-syntax).\n", + "* printf-like [old-style formatting](https://docs.python.org/3/library/stdtypes.html#old-string-formatting)\n", "* bash-like [template-strings](https://docs.python.org/3/library/string.html#template-strings)\n", "\n", "Here we provide a single example using the first three methods, so you can recognize them in the future.\n", @@ -599,7 +621,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This code block will fail in fslpython, since it uses python 3.5.\n", + "These f-strings are extremely useful when creating print or error messages for debugging, \n", + "especially with the new support for self-documenting in python 3.8 (see \n", + "[here](https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging)):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 3\n", + "b = 1/3\n", + "\n", + "print(f'{a + b=}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that this prints both the expression `a + b` and the output (this block will raise an error for python <= 3.7). \n", "\n", "\n", "<a class=\"anchor\" id=\"extracting-information-from-strings\"></a>\n", @@ -614,7 +657,7 @@ "\n", "<a class=\"anchor\" id=\"splitting-strings\"></a>\n", "### Splitting strings\n", - "The simplest way to extract a sub-string is to use slicing" + "The simplest way to extract a sub-string is to use slicing (see previous practical for more details):" ] }, { diff --git a/getting_started/02_text_io.md b/getting_started/02_text_io.md index 42e93b0..7000a1f 100644 --- a/getting_started/02_text_io.md +++ b/getting_started/02_text_io.md @@ -24,15 +24,15 @@ empty_string. * [Reading/writing files](#reading-writing-files) * [Creating new strings](#creating-new-strings) - * [String syntax](#string-syntax) - * [Unicode versus bytes](#unicode-versus-bytes) - * [Converting objects into strings](#converting-objects-into-strings) - * [Combining strings](#combining-strings) - * [String formattings](#string-formatting) + * [String syntax](#string-syntax) + * [Unicode versus bytes](#unicode-versus-bytes) + * [Converting objects into strings](#converting-objects-into-strings) + * [Combining strings](#combining-strings) + * [String formattings](#string-formatting) * [Extracting information from strings](#extracting-information-from-strings) - * [Splitting strings](#splitting-strings) - * [Converting strings to numbers](#converting-strings-to-numbers) - * [Regular expressions](#regular-expressions) + * [Splitting strings](#splitting-strings) + * [Converting strings to numbers](#converting-strings-to-numbers) + * [Regular expressions](#regular-expressions) * [Exercises](#exercises) <a class="anchor" id="reading-writing-files"></a> @@ -46,7 +46,8 @@ The syntax to open a file in python is `with open(<filename>, <mode>) as * `mode` is one of `'r'` (for read-only access), `'w'` (for writing a file, this wipes out any existing content), `'a'` (for appending to an existing - file). + file). A `'b'` can be added to any of these to open the file in "byte"-mode, + which prevents python from interpreting non-text (e.g., NIFTI) files as text. * `file_object` is a variable name which will be used within the `block of code` to access the opened file. @@ -73,11 +74,13 @@ with open('README.md', 'r') as readme_file: # each line is returned with its # newline character still intact, # so we use rstrip() to remove it. - print('{}: {}'.format(i, line.rstrip())) + print(f'{i}: {line.rstrip()}')) if i == 4: break ``` +> enumerate takes any sequence and returns 2-element tuples with the index and the sequence item + A very similar syntax is used to write files: ``` with open('02_text_io/my_file', 'w') as my_file: @@ -85,7 +88,7 @@ with open('02_text_io/my_file', 'w') as my_file: my_file.writelines(['Second line\n', 'and the third\n']) ``` -Note that no new line characters get added automatically. We can investigate +Note that new line characters do not get added automatically. We can investigate the resulting file using ``` @@ -143,6 +146,12 @@ a_string = "This is the first line.\nAnd here is the second.\n\tThe third starts print(a_string) ``` +You can even include unicode characters: +``` +a_string = "Python = ðŸ" +print(a_string) +``` + However, the easiest way to create multi-line strings is to use a triple quote (again single or double quotes can be used). Triple quotes allow your string to span multiple lines: ``` multi_line_string = """This is the first line. @@ -162,6 +171,7 @@ One pitfall when creating a list of strings is that python automatically concate my_list_of_strings = ['a', 'b', 'c' 'd', 'e'] print("The 'c' and 'd' got concatenated, because we forgot the comma:", my_list_of_strings) ``` +> This will lead to a syntax warning in python 3.8 or greater <a class="anchor" id="unicode-versus-bytes"></a> #### unicode versus bytes @@ -227,7 +237,7 @@ with open(op.expandvars('${FSLDIR}/data/standard/MNI152_T1_1mm.nii.gz'), 'rb') a <a class="anchor" id="converting-objects-into-strings"></a> -### converting objects into strings +### Converting objects into strings There are two functions to convert python objects into strings, `repr()` and `str()`. All other functions that rely on string-representations of python @@ -286,9 +296,9 @@ print(full_string) <a class="anchor" id="string-formatting"></a> ### String formatting Using the techniques in [Combining strings](#combining-strings) we can build simple strings. For longer strings it is often useful to first write a template strings with some placeholders, where variables are later inserted. Built into python are currently 4 different ways of doing this (with many packages providing similar capabilities): -* the recommended [new-style formatting](https://docs.python.org/3/library/string.html#format-string-syntax). -* printf-like [old-style formatting](https://docs.python.org/3/library/stdtypes.html#old-string-formatting) * [formatted string literals](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) (these are only available in python 3.6+) +* [new-style formatting](https://docs.python.org/3/library/string.html#format-string-syntax). +* printf-like [old-style formatting](https://docs.python.org/3/library/stdtypes.html#old-string-formatting) * bash-like [template-strings](https://docs.python.org/3/library/string.html#template-strings) Here we provide a single example using the first three methods, so you can recognize them in the future. @@ -321,7 +331,17 @@ b = 1/3 print(f'{a + b:.3f} = {a} + {b:.3f}') ``` -This code block will fail in fslpython, since it uses python 3.5. + +These f-strings are extremely useful when creating print or error messages for debugging, +especially with the new support for self-documenting in python 3.8 (see +[here](https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging)): +``` +a = 3 +b = 1/3 + +print(f'{a + b=}') +``` +Note that this prints both the expression `a + b` and the output (this block will raise an error for python <= 3.7). <a class="anchor" id="extracting-information-from-strings"></a> @@ -336,7 +356,7 @@ practcals. <a class="anchor" id="splitting-strings"></a> ### Splitting strings -The simplest way to extract a sub-string is to use slicing +The simplest way to extract a sub-string is to use slicing (see previous practical for more details): ``` a_string = 'abcdefghijklmnopqrstuvwxyz' print(a_string[10]) # create a string containing only the 11th character -- GitLab