Release 0.1.0

After refurbishing the project we prepare a new relaease.
There are no changes with respect to the contents as compared to v0.0.0
that are noteworthy release notes.
This commit is contained in:
Alexander Hess 2024-04-08 22:13:31 +02:00
commit 94e5112f10
Signed by: alexander
GPG key ID: 344EA5AB10D868E0
65 changed files with 387 additions and 387 deletions

View file

@ -8,7 +8,7 @@
}
},
"source": [
"**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_mb.png\">](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/11_classes/02_content.ipynb)."
"**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_mb.png\">](https://mybinder.org/v2/gh/webartifex/intro-to-python/main?urlpath=lab/tree/11_classes/02_content.ipynb)."
]
},
{
@ -52,7 +52,7 @@
}
},
"source": [
"As discussed in detail in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/07_sequences/00_content.ipynb#Collections-vs.-Sequences), a sequence is any finite and iterable container type with a *predictable* order of its elements such that we can label each element with an index in the range `0 <= index < len(sequence)`.\n",
"As discussed in detail in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/main/07_sequences/00_content.ipynb#Collections-vs.-Sequences), a sequence is any finite and iterable container type with a *predictable* order of its elements such that we can label each element with an index in the range `0 <= index < len(sequence)`.\n",
"\n",
"To make `Vector` and `Matrix` instances emulate sequences, we implement the `.__len__()` (cf., [reference <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/reference/datamodel.html#object.__len__)) and `.__getitem__()` (cf., [reference <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/reference/datamodel.html#object.__getitem__)) methods. While the former returns the total number of elements in a container and is automatically invoked on any object passed to the built-in [len() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#len) function, the latter is invoked by the interpreter behind the scenes when we use the indexing operator `[]`.\n",
"\n",
@ -714,7 +714,7 @@
"\n",
"The collection of all such behaviors a programming language offers is commonly referred to as its **object model**. In Python, the term **data model** is used instead and all possible behaviors are documented in the [language reference <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/reference/datamodel.html), in particular, in the section on special methods. We can think of the data model as the collection of all the behaviors we can make our user-defined data types follow. Pythonistas also use the term **protocol** instead of behavior, for example, we may say that \"the `Vector` and `Matrix` classes follow the sequence protocol.\"\n",
"\n",
"So, merely defining the *two* `.__len__()` and `.__getitem__()` methods is enough to make instances of any user-defined type behave like the built-in sequences in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/07_sequences/00_content.ipynb). Yet, there we defined sequences as all objects having the *four* properties of being finite, iterable, and ordered container types. And, these properties correspond to special methods by the names of `.__len__()`, `.__iter__()`, `.__reversed__()`, and `.__contains__()` as we see in the next section. Thus, Python \"magically\" knows how to derive the logic for the `.__iter__()`, `.__reversed__()`, and `.__contains__()` methods from the combination of the `.__len__()` and `.__getitem__()` methods. In general, while some special methods are related, others are not. Understanding these relationships means understanding the Python data model and vice versa. That is what every aspiring data scientist should aim for.\n",
"So, merely defining the *two* `.__len__()` and `.__getitem__()` methods is enough to make instances of any user-defined type behave like the built-in sequences in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/main/07_sequences/00_content.ipynb). Yet, there we defined sequences as all objects having the *four* properties of being finite, iterable, and ordered container types. And, these properties correspond to special methods by the names of `.__len__()`, `.__iter__()`, `.__reversed__()`, and `.__contains__()` as we see in the next section. Thus, Python \"magically\" knows how to derive the logic for the `.__iter__()`, `.__reversed__()`, and `.__contains__()` methods from the combination of the `.__len__()` and `.__getitem__()` methods. In general, while some special methods are related, others are not. Understanding these relationships means understanding the Python data model and vice versa. That is what every aspiring data scientist should aim for.\n",
"\n",
"On the contrary, we could also look at special methods individually. Whereas `.__len__()` is invoked on the object passed to [len() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#len), Python \"translates\" the indexing operator applied on any name like `a[i]`, for example, into the method invocation `a.__getitem__(i)`. So, in both cases, the special methods are executed according to a deterministic rule of the language. In that sense, they act as some sort of syntactic sugar. Thus, they even work if only one of them is defined. For example, without `.__len__()`, iteration with a `for`-loop still works but only in forward direction."
]
@ -1047,7 +1047,7 @@
"source": [
"In the above implementations, the instance attribute `._entries` on a `Vector` or `Matrix` instance references either a `list` or a `list` of row `list`s , which is by the convention of the leading underscore `_` an implementation detail. If users of our classes adhere to this convention, `Vector` and `Matrix` instances can be regarded as *immutable*.\n",
"\n",
"In line with the implied immutability, we implemented the `.transpose()` method such that it returns a *new* `Matrix` instance. Instead, we could make the method change the internal `self._entries` attribute *in place* as we do in the next example. To indicate this mutation to the user of the `Matrix` class clearly, the revised `.transpose()` method returns `None`. That mirrors, for example, how the mutating methods of the built-in `list` type behave (cf., [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/07_sequences/01_content.ipynb#List-Methods)).\n",
"In line with the implied immutability, we implemented the `.transpose()` method such that it returns a *new* `Matrix` instance. Instead, we could make the method change the internal `self._entries` attribute *in place* as we do in the next example. To indicate this mutation to the user of the `Matrix` class clearly, the revised `.transpose()` method returns `None`. That mirrors, for example, how the mutating methods of the built-in `list` type behave (cf., [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/main/07_sequences/01_content.ipynb#List-Methods)).\n",
"\n",
"Such decisions are better made consciously when designing a custom data type. The main trade-off is that immutable data types are typically easier to reason about when reading code whereas mutable data types tend to be more memory efficient and make programs faster as less copying operations take place in memory. However, this trade-off only becomes critical when we deal with big amounts of data."
]
@ -1577,7 +1577,7 @@
}
},
"source": [
"After this discussion of mutable `Vector` and `Matrix` classes, we continue with immutable implementations in the rest of this chapter. To lower the chance that we accidently design parts of our classes to be mutable, we replace the built-in [list() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#func-list) constructor with [tuple() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#func-tuple) in the `.__init__()` methods. As we learn in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/07_sequences/03_content.ipynb#Tuples-are-like-%22Immutable-Lists%22), `tuple`s are like immutable `list`s."
"After this discussion of mutable `Vector` and `Matrix` classes, we continue with immutable implementations in the rest of this chapter. To lower the chance that we accidently design parts of our classes to be mutable, we replace the built-in [list() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#func-list) constructor with [tuple() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#func-tuple) in the `.__init__()` methods. As we learn in [Chapter 7 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/main/07_sequences/03_content.ipynb#Tuples-are-like-%22Immutable-Lists%22), `tuple`s are like immutable `list`s."
]
},
{
@ -1599,7 +1599,7 @@
}
},
"source": [
"A function is considered **polymorphic** if it can work with *different* data types. The main advantage is reuse of the function's code. Polymorphism goes hand in hand with the concept of [duck typing <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_wiki.png\">](https://en.wikipedia.org/wiki/Duck_typing), first mentioned in [Chapter 4 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/04_iteration/00_content.ipynb#Duck-Typing) in the context of input validation.\n",
"A function is considered **polymorphic** if it can work with *different* data types. The main advantage is reuse of the function's code. Polymorphism goes hand in hand with the concept of [duck typing <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_wiki.png\">](https://en.wikipedia.org/wiki/Duck_typing), first mentioned in [Chapter 4 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/main/04_iteration/00_content.ipynb#Duck-Typing) in the context of input validation.\n",
"\n",
"We know polymorphic functions already: The built-in [sum() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#sum) function is a trivial example that works with all kinds of `iterable` arguments."
]