Add initial version of chapter 11, part 4
This commit is contained in:
parent
8dc67c5bdd
commit
85b7fd274c
9 changed files with 2927 additions and 222 deletions
|
@ -1571,7 +1571,7 @@
|
|||
}
|
||||
},
|
||||
"source": [
|
||||
"Packages are a generalization of modules, and we look at one in detail in [Chapter 11 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/11_classes/00_content.ipynb). You may, however, already look at a [sample package <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes/sample_package) in the repository, which is nothing but a folder with *.py* files in it.\n",
|
||||
"Packages are a generalization of modules, and we look at one in detail in [Chapter 11 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/11_classes/04_content.ipynb#Packages-vs.-Modules).\n",
|
||||
"\n",
|
||||
"As a further reading on modules and packages, we refer to the [official tutorial <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/tutorial/modules.html)."
|
||||
]
|
||||
|
|
|
@ -800,41 +800,6 @@
|
|||
"type(v)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"Every instance comes with a special `.__class__` attribute that also references the corresponding class object."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"__main__.Vector"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"v.__class__"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
|
@ -848,7 +813,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -861,7 +826,7 @@
|
|||
"<__main__.Vector at 0x7f9b9416d760>"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -885,7 +850,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -910,7 +875,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -946,7 +911,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -983,7 +948,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"execution_count": 25,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -996,7 +961,7 @@
|
|||
"[1.0, 2.0, 3.0]"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1031,7 +996,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"execution_count": 26,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1044,7 +1009,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"execution_count": 27,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1057,7 +1022,7 @@
|
|||
"(1, 2, 3)"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1068,7 +1033,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"execution_count": 28,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1081,7 +1046,7 @@
|
|||
"(1, 2, 3)"
|
||||
]
|
||||
},
|
||||
"execution_count": 29,
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1103,7 +1068,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"execution_count": 29,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1144,7 +1109,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"execution_count": 30,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1157,7 +1122,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"execution_count": 31,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1170,7 +1135,7 @@
|
|||
"Vector((1.000, 2.000, 3.000))"
|
||||
]
|
||||
},
|
||||
"execution_count": 32,
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1192,7 +1157,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"execution_count": 32,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1205,7 +1170,7 @@
|
|||
"Vector((1.000, 2.000, 3.000))"
|
||||
]
|
||||
},
|
||||
"execution_count": 33,
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1227,7 +1192,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"execution_count": 33,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1240,7 +1205,7 @@
|
|||
"'Vector((1.000, 2.000, 3.000))'"
|
||||
]
|
||||
},
|
||||
"execution_count": 34,
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1266,7 +1231,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"execution_count": 34,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1279,7 +1244,7 @@
|
|||
"'Vector(1.0, ..., 3.0)[3]'"
|
||||
]
|
||||
},
|
||||
"execution_count": 35,
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1301,7 +1266,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"execution_count": 35,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1342,14 +1307,14 @@
|
|||
}
|
||||
},
|
||||
"source": [
|
||||
"Below is a first implementation of the `Matrix` class that stores the entries internally as a `list` of `list`s.\n",
|
||||
"Below is a first implementation of the `Matrix` class that stores the `._entries` internally as a `list` of `list`s.\n",
|
||||
"\n",
|
||||
"The `.__init__()` method ensures that all the rows come with the same number of columns. Again, we do not allow `Matrix` instances without any entries."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"execution_count": 36,
|
||||
"metadata": {
|
||||
"code_folding": [],
|
||||
"slideshow": {
|
||||
|
@ -1391,7 +1356,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"execution_count": 37,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1404,7 +1369,7 @@
|
|||
"94113690738160"
|
||||
]
|
||||
},
|
||||
"execution_count": 38,
|
||||
"execution_count": 37,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1415,7 +1380,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"execution_count": 38,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1428,7 +1393,7 @@
|
|||
"type"
|
||||
]
|
||||
},
|
||||
"execution_count": 39,
|
||||
"execution_count": 38,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1439,7 +1404,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 40,
|
||||
"execution_count": 39,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1452,7 +1417,7 @@
|
|||
"__main__.Matrix"
|
||||
]
|
||||
},
|
||||
"execution_count": 40,
|
||||
"execution_count": 39,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1474,7 +1439,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 41,
|
||||
"execution_count": 40,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1487,7 +1452,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 42,
|
||||
"execution_count": 41,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1500,7 +1465,7 @@
|
|||
"140306180401856"
|
||||
]
|
||||
},
|
||||
"execution_count": 42,
|
||||
"execution_count": 41,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1511,7 +1476,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 43,
|
||||
"execution_count": 42,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1524,7 +1489,7 @@
|
|||
"__main__.Matrix"
|
||||
]
|
||||
},
|
||||
"execution_count": 43,
|
||||
"execution_count": 42,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1546,7 +1511,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 44,
|
||||
"execution_count": 43,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1559,7 +1524,7 @@
|
|||
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
||||
]
|
||||
},
|
||||
"execution_count": 44,
|
||||
"execution_count": 43,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1570,7 +1535,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 45,
|
||||
"execution_count": 44,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1602,7 +1567,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 46,
|
||||
"execution_count": 45,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "skip"
|
||||
|
@ -1628,7 +1593,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 47,
|
||||
"execution_count": 46,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1673,12 +1638,14 @@
|
|||
"source": [
|
||||
"The methods we have seen so far are all **instance methods**. The characteristic idea behind an instance method is that the behavior it provides either depends on the state of a concrete instance or mutates it. In other words, an instance method *always* works with attributes on the `self` argument. If a method does *not* need access to `self` to do its job, it is conceptually *not* an instance method and we should probably convert it into another kind of method as shown below.\n",
|
||||
"\n",
|
||||
"An example of an instance method from linear algebra is the `.transpose()` method below that switches the rows and columns of an *existing* `Matrix` instance and returns a *new* `Matrix` instance based off that. It is implemented by passing the *iterator* created with the [zip() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#zip) built-in as the `data` argument to the `Matrix` constructor: The expression `zip(*self._entries)` may be a bit hard to understand because of the involved unpacking but simply flips a `Vector`'s rows and columns. 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 within the `.__init__()` method then materializes the iterator into the `._entries`. Without a concrete `Matrix`'s rows and columns, `.transpose()` does not make sense, conceptually speaking."
|
||||
"An example of an instance method from linear algebra is the `.transpose()` method below that switches the rows and columns of an *existing* `Matrix` instance and returns a *new* `Matrix` instance based off that. It is implemented by passing the *iterator* created with the [zip() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#zip) built-in as the `data` argument to the `Matrix` constructor: The expression `zip(*self._entries)` may be a bit hard to understand because of the involved unpacking but simply flips a `Matrix`'s rows and columns. 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 within the `.__init__()` method then materializes the iterator into the `._entries` attribute. Without a concrete `Matrix`'s rows and columns, `.transpose()` does not make sense, conceptually speaking.\n",
|
||||
"\n",
|
||||
"Also, we see that it is ok to reference a class from within one of its methods. While this seems trivial to some readers, others may find this confusing. The final versions of the `Vector` and `Matrix` classes in the [fourth part <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/11_classes/04_content.ipynb#The-final-Vector-and-Matrix-Classes) of this chapter show how this \"hard coded\" redundancy can be avoided."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 48,
|
||||
"execution_count": 47,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1713,7 +1680,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 49,
|
||||
"execution_count": 48,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1726,7 +1693,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 50,
|
||||
"execution_count": 49,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1739,7 +1706,7 @@
|
|||
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
||||
]
|
||||
},
|
||||
"execution_count": 50,
|
||||
"execution_count": 49,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1750,7 +1717,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 51,
|
||||
"execution_count": 50,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1763,7 +1730,7 @@
|
|||
"Matrix(((1.000, 4.000, 7.000,), (2.000, 5.000, 8.000,), (3.000, 6.000, 9.000,)))"
|
||||
]
|
||||
},
|
||||
"execution_count": 51,
|
||||
"execution_count": 50,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1785,7 +1752,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 52,
|
||||
"execution_count": 51,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1798,7 +1765,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 53,
|
||||
"execution_count": 52,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1811,7 +1778,7 @@
|
|||
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
||||
]
|
||||
},
|
||||
"execution_count": 53,
|
||||
"execution_count": 52,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1822,7 +1789,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 54,
|
||||
"execution_count": 53,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1835,7 +1802,7 @@
|
|||
"False"
|
||||
]
|
||||
},
|
||||
"execution_count": 54,
|
||||
"execution_count": 53,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1857,7 +1824,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 55,
|
||||
"execution_count": 54,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1870,7 +1837,7 @@
|
|||
"False"
|
||||
]
|
||||
},
|
||||
"execution_count": 55,
|
||||
"execution_count": 54,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1894,7 +1861,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 56,
|
||||
"execution_count": 55,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1933,7 +1900,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 57,
|
||||
"execution_count": 56,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -1946,7 +1913,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 58,
|
||||
"execution_count": 57,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -1959,7 +1926,7 @@
|
|||
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
||||
]
|
||||
},
|
||||
"execution_count": 58,
|
||||
"execution_count": 57,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -2007,7 +1974,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 59,
|
||||
"execution_count": 58,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -2051,7 +2018,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 60,
|
||||
"execution_count": 59,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "slide"
|
||||
|
@ -2064,7 +2031,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 61,
|
||||
"execution_count": 60,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
@ -2077,7 +2044,7 @@
|
|||
"(2, 3)"
|
||||
]
|
||||
},
|
||||
"execution_count": 61,
|
||||
"execution_count": 60,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -2099,7 +2066,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 62,
|
||||
"execution_count": 61,
|
||||
"metadata": {
|
||||
"slideshow": {
|
||||
"slide_type": "fragment"
|
||||
|
|
|
@ -1577,7 +1577,7 @@
|
|||
}
|
||||
},
|
||||
"source": [
|
||||
"After this discussion of mutable `Vector` and `Matrix` classes, we continue with immutable classes in the rest of this chapter."
|
||||
"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."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
"class Vector:\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(float(x) for x in data)\n",
|
||||
" self._entries = tuple(float(x) for x in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
@ -111,7 +111,7 @@
|
|||
"class Matrix:\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(list(float(x) for x in r) for r in data)\n",
|
||||
" self._entries = tuple(tuple(float(x) for x in r) for r in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
@ -678,7 +678,7 @@
|
|||
"class Vector:\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(float(x) for x in data)\n",
|
||||
" self._entries = tuple(float(x) for x in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
@ -692,7 +692,7 @@
|
|||
" return iter(self._entries)\n",
|
||||
"\n",
|
||||
" def __add__(self, other):\n",
|
||||
" if isinstance(other, self.__class__): # vector addition\n",
|
||||
" if isinstance(other, Vector): # vector addition\n",
|
||||
" if len(self) != len(other):\n",
|
||||
" raise ValueError(\"vectors must be of the same length\")\n",
|
||||
" return Vector(x + y for (x, y) in zip(self, other))\n",
|
||||
|
@ -704,7 +704,7 @@
|
|||
" return self + other\n",
|
||||
"\n",
|
||||
" def __sub__(self, other):\n",
|
||||
" if isinstance(other, self.__class__): # vector subtraction\n",
|
||||
" if isinstance(other, Vector): # vector subtraction\n",
|
||||
" if len(self) != len(other):\n",
|
||||
" raise ValueError(\"vectors must be of the same length\")\n",
|
||||
" return Vector(x - y for (x, y) in zip(self, other))\n",
|
||||
|
@ -719,7 +719,7 @@
|
|||
" return NotImplemented\n",
|
||||
"\n",
|
||||
" def __mul__(self, other):\n",
|
||||
" if isinstance(other, self.__class__): # dot product\n",
|
||||
" if isinstance(other, Vector): # dot product\n",
|
||||
" if len(self) != len(other):\n",
|
||||
" raise ValueError(\"vectors must be of the same length\")\n",
|
||||
" return sum(x * y for (x, y) in zip(self, other))\n",
|
||||
|
@ -1142,7 +1142,7 @@
|
|||
"class Matrix:\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(list(float(x) for x in r) for r in data)\n",
|
||||
" self._entries = tuple(tuple(float(x) for x in r) for r in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
@ -1169,7 +1169,7 @@
|
|||
" return (self._entries[r][c] for r in range(self.n_rows) for c in range(self.n_cols))\n",
|
||||
"\n",
|
||||
" def __add__(self, other):\n",
|
||||
" if isinstance(other, self.__class__): # matrix addition\n",
|
||||
" if isinstance(other, Matrix): # matrix addition\n",
|
||||
" if (self.n_rows != other.n_rows) or (self.n_cols != other.n_cols):\n",
|
||||
" raise ValueError(\"matrices must have the same dimensions\")\n",
|
||||
" return Matrix((s_col + o_col for (s_col, o_col) in zip(s_row, o_row))\n",
|
||||
|
@ -1184,7 +1184,7 @@
|
|||
" return self + other\n",
|
||||
"\n",
|
||||
" def __sub__(self, other):\n",
|
||||
" if isinstance(other, self.__class__): # matrix subtraction\n",
|
||||
" if isinstance(other, Matrix): # matrix subtraction\n",
|
||||
" if (self.n_rows != other.n_rows) or (self.n_cols != other.n_cols):\n",
|
||||
" raise ValueError(\"matrices must have the same dimensions\")\n",
|
||||
" return Matrix((s_col - o_col for (s_col, o_col) in zip(s_row, o_row))\n",
|
||||
|
@ -1211,7 +1211,7 @@
|
|||
" return Matrix((x * other for x in r) for r in self._entries)\n",
|
||||
" elif isinstance(other, Vector):\n",
|
||||
" return self._matrix_multiply(other.as_matrix()).as_vector()\n",
|
||||
" elif isinstance(other, self.__class__):\n",
|
||||
" elif isinstance(other, Matrix):\n",
|
||||
" return self._matrix_multiply(other)\n",
|
||||
" return NotImplemented\n",
|
||||
"\n",
|
||||
|
@ -1720,7 +1720,7 @@
|
|||
" zero_threshold = 1e-12\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(float(x) for x in data)\n",
|
||||
" self._entries = tuple(float(x) for x in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
@ -1734,7 +1734,7 @@
|
|||
" return iter(self._entries)\n",
|
||||
"\n",
|
||||
" def __eq__(self, other):\n",
|
||||
" if isinstance(other, self.__class__):\n",
|
||||
" if isinstance(other, Vector):\n",
|
||||
" if len(self) != len(other):\n",
|
||||
" raise ValueError(\"vectors must be of the same length\")\n",
|
||||
" for x, y in zip(self, other):\n",
|
||||
|
@ -1990,7 +1990,7 @@
|
|||
"class Vector:\n",
|
||||
"\n",
|
||||
" def __init__(self, data):\n",
|
||||
" self._entries = list(float(x) for x in data)\n",
|
||||
" self._entries = tuple(float(x) for x in data)\n",
|
||||
" # ...\n",
|
||||
"\n",
|
||||
" def __repr__(self):\n",
|
||||
|
|
2719
11_classes/04_content.ipynb
Normal file
2719
11_classes/04_content.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
@ -28,3 +28,7 @@ from sample_package.vector import Vector
|
|||
__name__ = "linear_algebra_tools"
|
||||
__version__ = "0.1.0" # see https://semver.org/ for how the format works
|
||||
__author__ = "Alexander Hess"
|
||||
|
||||
# Define what is imported with the "star import"
|
||||
# (i.e., with `from sample_package import *`).
|
||||
__all__ = ["Matrix", "Vector"]
|
||||
|
|
|
@ -17,12 +17,14 @@ class Matrix:
|
|||
defaults to tuple
|
||||
typing (callable): type casting applied to all entries upon creation;
|
||||
defaults to float
|
||||
vector_cls (vector.Vector): a reference to the Vector class to work with
|
||||
zero_threshold (float): max. tolerance when comparing an entry to zero;
|
||||
defaults to 1e-12
|
||||
"""
|
||||
|
||||
storage = utils.DEFAULT_ENTRIES_STORAGE
|
||||
typing = utils.DEFAULT_ENTRY_TYPE
|
||||
# the `vector_cls` attribute is set at the bottom of this file
|
||||
zero_threshold = utils.ZERO_THRESHOLD
|
||||
|
||||
def __init__(self, data):
|
||||
|
@ -156,7 +158,7 @@ class Matrix:
|
|||
Returns:
|
||||
rows (generator): produces a Matrix's rows as Vectors
|
||||
"""
|
||||
return (Vector(r) for r in self._entries)
|
||||
return (self.vector_cls(r) for r in self._entries)
|
||||
|
||||
def cols(self):
|
||||
"""Loop over a Matrix's columns.
|
||||
|
@ -165,7 +167,7 @@ class Matrix:
|
|||
columns (generator): produces a Matrix's columns as Vectors
|
||||
"""
|
||||
return (
|
||||
Vector(self._entries[r][c] for r in range(self.n_rows))
|
||||
self.vector_cls(self._entries[r][c] for r in range(self.n_rows))
|
||||
for c in range(self.n_cols)
|
||||
)
|
||||
|
||||
|
@ -232,7 +234,7 @@ class Matrix:
|
|||
|
||||
def __radd__(self, other):
|
||||
"""See docstring for .__add__()."""
|
||||
if isinstance(other, Vector):
|
||||
if isinstance(other, self.vector_cls):
|
||||
raise TypeError("vectors and matrices cannot be added")
|
||||
# As both matrix and broadcasting addition are commutative,
|
||||
# we dispatch to .__add__().
|
||||
|
@ -260,7 +262,7 @@ class Matrix:
|
|||
|
||||
def __rsub__(self, other):
|
||||
"""See docstring for .__sub__()."""
|
||||
if isinstance(other, Vector):
|
||||
if isinstance(other, self.vector_cls):
|
||||
raise TypeError("vectors and matrices cannot be subtracted")
|
||||
# Same comments as in .__sub__() apply
|
||||
# with the roles of self and other swapped.
|
||||
|
@ -294,6 +296,8 @@ class Matrix:
|
|||
|
||||
Matrix-vector and vector-matrix multiplication are not commutative.
|
||||
|
||||
>>> from sample_package import Vector
|
||||
|
||||
>>> Matrix([(1, 2), (3, 4)]) * Vector([5, 6])
|
||||
Vector((17.000, 39.000))
|
||||
|
||||
|
@ -304,7 +308,7 @@ class Matrix:
|
|||
if isinstance(other, numbers.Number):
|
||||
return self.__class__((x * other for x in r) for r in self._entries)
|
||||
# Matrix-vector multiplication: Vector is a column Vector
|
||||
elif isinstance(other, Vector):
|
||||
elif isinstance(other, self.vector_cls):
|
||||
# First, cast the other Vector as a Matrix, then do matrix-matrix
|
||||
# multiplication, and lastly return the result as a Vector again.
|
||||
return self._matrix_multiply(other.as_matrix()).as_vector()
|
||||
|
@ -319,7 +323,7 @@ class Matrix:
|
|||
if isinstance(other, numbers.Number):
|
||||
return self * other
|
||||
# Vector-matrix multiplication: Vector is a row Vector
|
||||
elif isinstance(other, Vector):
|
||||
elif isinstance(other, self.vector_cls):
|
||||
return other.as_matrix(column=False)._matrix_multiply(self).as_vector()
|
||||
return NotImplemented
|
||||
|
||||
|
@ -375,7 +379,7 @@ class Matrix:
|
|||
|
||||
def __abs__(self):
|
||||
"""The Frobenius norm of a Matrix."""
|
||||
return utils.norm(self) # use the norm() function shared with the Vector class
|
||||
return utils.norm(self) # uses the norm() function shared vector.Vector
|
||||
|
||||
def __bool__(self):
|
||||
"""A Matrix is truthy if its Frobenius norm is strictly positive."""
|
||||
|
@ -398,7 +402,7 @@ class Matrix:
|
|||
"""Get a Vector representation of a Matrix.
|
||||
|
||||
Returns:
|
||||
vector (Vector)
|
||||
vector (vector.Vector)
|
||||
|
||||
Raises:
|
||||
RuntimeError: if one of the two dimensions, .n_rows or .n_cols, is not 1
|
||||
|
@ -409,7 +413,7 @@ class Matrix:
|
|||
"""
|
||||
if not (self.n_rows == 1 or self.n_cols == 1):
|
||||
raise RuntimeError("one dimension (m or n) must be 1")
|
||||
return Vector(x for x in self)
|
||||
return self.vector_cls(x for x in self)
|
||||
|
||||
def transpose(self):
|
||||
"""Switch the rows and columns of a Matrix.
|
||||
|
@ -432,4 +436,8 @@ class Matrix:
|
|||
# We call that a circular import. Whereas Python handles "circular" references
|
||||
# (e.g., both the Matrix and Vector classes have methods that reference the
|
||||
# respective other class), that is forbidden for imports.
|
||||
from sample_package.vector import Vector
|
||||
from sample_package import vector
|
||||
|
||||
# This attribute cannot be set in the class definition
|
||||
# as the vector module is only imported down here.
|
||||
Matrix.vector_cls = vector.Vector
|
||||
|
|
|
@ -7,8 +7,8 @@ import numbers
|
|||
# If third-party libraries are needed, they are
|
||||
# put into a group on their own in between.
|
||||
# Within a group, imports are sorted lexicographically.
|
||||
from sample_package import matrix
|
||||
from sample_package import utils
|
||||
from sample_package.matrix import Matrix
|
||||
|
||||
|
||||
class Vector:
|
||||
|
@ -17,6 +17,7 @@ class Vector:
|
|||
All entries are converted to floats, or whatever is set in the typing attribute.
|
||||
|
||||
Attributes:
|
||||
matrix_cls (matrix.Matrix): a reference to the Matrix class to work with
|
||||
storage (callable): data type used to store the entries internally;
|
||||
defaults to tuple
|
||||
typing (callable): type casting applied to all entries upon creation;
|
||||
|
@ -25,6 +26,7 @@ class Vector:
|
|||
defaults to 1e-12
|
||||
"""
|
||||
|
||||
matrix_cls = matrix.Matrix
|
||||
storage = utils.DEFAULT_ENTRIES_STORAGE
|
||||
typing = utils.DEFAULT_ENTRY_TYPE
|
||||
zero_threshold = utils.ZERO_THRESHOLD
|
||||
|
@ -219,7 +221,7 @@ class Vector:
|
|||
|
||||
def __abs__(self):
|
||||
"""The Euclidean norm of a vector."""
|
||||
return utils.norm(self) # use the norm() function shared with the Matrix class
|
||||
return utils.norm(self) # uses the norm() function shared matrix.Matrix
|
||||
|
||||
def __bool__(self):
|
||||
"""A Vector is truthy if its Euclidean norm is strictly positive."""
|
||||
|
@ -246,7 +248,7 @@ class Vector:
|
|||
column vector or a row vector; defaults to True
|
||||
|
||||
Returns:
|
||||
matrix (Matrix)
|
||||
matrix (matrix.Matrix)
|
||||
|
||||
Example Usage:
|
||||
>>> v = Vector([1, 2, 3])
|
||||
|
@ -256,5 +258,5 @@ class Vector:
|
|||
Matrix(((1.000, 2.000, 3.000,)))
|
||||
"""
|
||||
if column:
|
||||
return Matrix([x] for x in self)
|
||||
return Matrix([(x for x in self)])
|
||||
return self.matrix_cls([x] for x in self)
|
||||
return self.matrix_cls([(x for x in self)])
|
||||
|
|
|
@ -284,3 +284,8 @@ If this is not possible,
|
|||
[<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/03_content.ipynb)
|
||||
(Operator Overloading: Arithmetic & Relational Operators;
|
||||
Number Emulation)
|
||||
- [content <img height="12" style="display: inline-block" src="static/link/to_nb.png">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/11_classes/04_content.ipynb)
|
||||
[<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/04_content.ipynb)
|
||||
(Writing one's own Packages;
|
||||
The final `Vector` & `Matrix` Classes;
|
||||
Comparison with `numpy`)
|
||||
|
|
Loading…
Reference in a new issue