diff --git a/01-data-model/data-model.ipynb b/01-data-model/data-model.ipynb
index f525899..5b30397 100644
--- a/01-data-model/data-model.ipynb
+++ b/01-data-model/data-model.ipynb
@@ -482,7 +482,7 @@
" self.y = y\n",
"\n",
" def __repr__(self):\n",
- " return 'Vector(%r, %r)' % (self.x, self.y)\n",
+ " return f'Vector({self.x!r}, {self.y!r})'\n",
"\n",
" def __abs__(self):\n",
" return math.hypot(self.x, self.y)\n",
diff --git a/02-array-seq/array-seq.ipynb b/02-array-seq/array-seq.ipynb
index 032d811..afdbf6b 100644
--- a/02-array-seq/array-seq.ipynb
+++ b/02-array-seq/array-seq.ipynb
@@ -9,12 +9,14 @@
"**Sections with code snippets in this chapter:**\n",
"\n",
"* [List Comprehensions and Generator Expressions](#List-Comprehensions-and-Generator-Expressions)\n",
+ "* [Tuples Are Not Just Immutable Lists](#Tuples-Are-Not-Just-Immutable-Lists)\n",
+ "* [Unpacking sequences and iterables](#Unpacking-sequences-and-iterables)\n",
+ "* [Pattern Matching with Sequences](#Pattern-Matching-with-Sequences)\n",
"* [Slicing](#Slicing)\n",
- "* [Building Lists of Lists](#Building-Lists-of-Lists)\n",
+ "* [Using + and * with Sequences](#Using-+-and-*-with-Sequences)\n",
"* [Augmented Assignment with Sequences](#Augmented-Assignment-with-Sequences)\n",
"* [list.sort and the sorted Built-In Function](#list.sort-and-the-sorted-Built-In-Function)\n",
- "* [Managing Ordered Sequences with bisect](#Managing-Ordered-Sequences-with-bisect)\n",
- "* [Arrays](#Arrays)\n",
+ "* [When a List Is Not the Answer](#When-a-List-Is-Not-the-Answer)\n",
"* [Memory Views](#Memory-Views)\n",
"* [NumPy and SciPy](#NumPy-and-SciPy)\n",
"* [Deques and Other Queues](#Deques-and-Other-Queues)\n",
@@ -42,9 +44,7 @@
"outputs": [
{
"data": {
- "text/plain": [
- "[36, 162, 163, 165, 8364, 164]"
- ]
+ "text/plain": "[36, 162, 163, 165, 8364, 164]"
},
"execution_count": 1,
"metadata": {},
@@ -65,7 +65,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-2. Build a list of Unicode codepoints from a string, take 2"
+ "#### Example 2-2. Build a list of Unicode codepoints from a string, using a listcomp"
]
},
{
@@ -75,9 +75,7 @@
"outputs": [
{
"data": {
- "text/plain": [
- "[36, 162, 163, 165, 8364, 164]"
- ]
+ "text/plain": "[36, 162, 163, 165, 8364, 164]"
},
"execution_count": 2,
"metadata": {},
@@ -106,9 +104,7 @@
"outputs": [
{
"data": {
- "text/plain": [
- "'ABC'"
- ]
+ "text/plain": "'ABC'"
},
"execution_count": 3,
"metadata": {},
@@ -128,9 +124,7 @@
"outputs": [
{
"data": {
- "text/plain": [
- "[65, 66, 67]"
- ]
+ "text/plain": "[65, 66, 67]"
},
"execution_count": 4,
"metadata": {},
@@ -141,6 +135,30 @@
"codes"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "67"
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "codes = [last := ord(c) for c in x]\n",
+ "last"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -150,214 +168,958 @@
},
{
"cell_type": "code",
- "execution_count": 5,
- "metadata": {},
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "[162, 163, 165, 8364, 164]"
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "symbols = '$¢£¥€¤'\n",
+ "beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]\n",
+ "beyond_ascii"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "[162, 163, 165, 8364, 164]"
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))\n",
+ "beyond_ascii"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Example 2-4. Cartesian product using a list comprehension"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "[('black', 'S'),\n ('black', 'M'),\n ('black', 'L'),\n ('white', 'S'),\n ('white', 'M'),\n ('white', 'L')]"
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "colors = ['black', 'white']\n",
+ "sizes = ['S', 'M', 'L']\n",
+ "tshirts = [(color, size) for color in colors for size in sizes]\n",
+ "tshirts"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "('black', 'S')\n",
+ "('black', 'M')\n",
+ "('black', 'L')\n",
+ "('white', 'S')\n",
+ "('white', 'M')\n",
+ "('white', 'L')\n"
+ ]
+ }
+ ],
+ "source": [
+ "for color in colors:\n",
+ " for size in sizes:\n",
+ " print((color, size))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "[('black', 'S'),\n ('black', 'M'),\n ('black', 'L'),\n ('white', 'S'),\n ('white', 'M'),\n ('white', 'L')]"
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "shirts = [(color, size) for size in sizes\n",
+ " for color in colors]\n",
+ "tshirts"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Example 2-5. Initializing a tuple and an array from a generator expression"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(36, 162, 163, 165, 8364, 164)"
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "symbols = '$¢£¥€¤'\n",
+ "tuple(ord(symbol) for symbol in symbols)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "array('I', [36, 162, 163, 165, 8364, 164])"
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import array\n",
+ "\n",
+ "array.array('I', (ord(symbol) for symbol in symbols))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Example 2-6. Cartesian product in a generator expression"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "black S\n",
+ "black M\n",
+ "black L\n",
+ "white S\n",
+ "white M\n",
+ "white L\n"
+ ]
+ }
+ ],
+ "source": [
+ "colors = ['black', 'white']\n",
+ "sizes = ['S', 'M', 'L']\n",
+ "\n",
+ "for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):\n",
+ " print(tshirt)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Tuples Are Not Just Immutable Lists"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ },
+ "execution_count": 73
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "#### Example 2-7. Tuples used as records"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "BRA/CE342567\n",
+ "ESP/XDA205856\n",
+ "USA/31195855\n"
+ ]
+ }
+ ],
+ "source": [
+ "lax_coordinates = (33.9425, -118.408056)\n",
+ "city, year, pop, chg, area = ('Tokyo', 2003, 32_450, 0.66, 8014)\n",
+ "traveler_ids = [('USA', '31195855'), ('BRA', 'CE342567'), ('ESP', 'XDA205856')]\n",
+ "\n",
+ "for passport in sorted(traveler_ids):\n",
+ " print('%s/%s' % passport)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "USA\n",
+ "BRA\n",
+ "ESP\n"
+ ]
+ }
+ ],
+ "source": [
+ "for country, _ in traveler_ids:\n",
+ " print(country)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "### Tuples as Immutable Lists"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "True"
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a = (10, 'alpha', [1, 2])\n",
+ "b = (10, 'alpha', [1, 2])\n",
+ "a == b"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "False"
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "b[-1].append(99)\n",
+ "a == b"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(10, 'alpha', [1, 2, 99])"
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "b"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "True"
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def fixed(o):\n",
+ " try:\n",
+ " hash(o)\n",
+ " except TypeError:\n",
+ " return False\n",
+ " return True\n",
+ "\n",
+ "\n",
+ "tf = (10, 'alpha', (1, 2)) # Contains no mutable items\n",
+ "tm = (10, 'alpha', [1, 2]) # Contains a mutable item (list)\n",
+ "fixed(tf)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "False"
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fixed(tm)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Unpacking sequences and iterables"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "33.9425"
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "lax_coordinates = (33.9425, -118.408056)\n",
+ "latitude, longitude = lax_coordinates # unpacking\n",
+ "latitude"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "-118.408056"
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "longitude"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(2, 4)"
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "divmod(20, 8)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(2, 4)"
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "t = (20, 8)\n",
+ "divmod(*t)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(2, 4)"
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "quotient, remainder = divmod(*t)\n",
+ "quotient, remainder"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "'id_rsa.pub'"
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import os\n",
+ "\n",
+ "_, filename = os.path.split('/home/luciano/.ssh/id_rsa.pub')\n",
+ "filename"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "### Using * to grab excess items"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(0, 1, [2, 3, 4])"
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a, b, *rest = range(5)\n",
+ "a, b, rest"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "(0, 1, [2])"
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a, b, *rest = range(3)\n",
+ "a, b, rest"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
"outputs": [
{
"data": {
- "text/plain": [
- "[162, 163, 165, 8364, 164]"
- ]
+ "text/plain": "(0, 1, [])"
},
- "execution_count": 5,
+ "execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "symbols = '$¢£¥€¤'\n",
- "beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]\n",
- "beyond_ascii"
- ]
+ "a, b, *rest = range(2)\n",
+ "a, b, rest"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 6,
- "metadata": {},
+ "execution_count": 30,
"outputs": [
{
"data": {
- "text/plain": [
- "[162, 163, 165, 8364, 164]"
- ]
+ "text/plain": "(0, [1, 2], 3, 4)"
},
- "execution_count": 6,
+ "execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))\n",
- "beyond_ascii"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Example 2-4. Cartesian product using a list comprehension"
- ]
+ "a, *body, c, d = range(5)\n",
+ "a, body, c, d"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 7,
- "metadata": {},
+ "execution_count": 31,
"outputs": [
{
"data": {
- "text/plain": [
- "[('black', 'S'),\n",
- " ('black', 'M'),\n",
- " ('black', 'L'),\n",
- " ('white', 'S'),\n",
- " ('white', 'M'),\n",
- " ('white', 'L')]"
- ]
+ "text/plain": "([0, 1], 2, 3, 4)"
},
- "execution_count": 7,
+ "execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "colors = ['black', 'white']\n",
- "sizes = ['S', 'M', 'L']\n",
- "tshirts = [(color, size) for color in colors for size in sizes]\n",
- "tshirts"
- ]
+ "*head, b, c, d = range(5)\n",
+ "head, b, c, d"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "### Unpacking with * in function calls and sequence literals"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 8,
- "metadata": {},
+ "execution_count": 32,
"outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "('black', 'S')\n",
- "('black', 'M')\n",
- "('black', 'L')\n",
- "('white', 'S')\n",
- "('white', 'M')\n",
- "('white', 'L')\n"
- ]
+ "data": {
+ "text/plain": "(1, 2, 3, 4, (5, 6))"
+ },
+ "execution_count": 32,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "for color in colors:\n",
- " for size in sizes:\n",
- " print((color, size))"
- ]
+ "def fun(a, b, c, d, *rest):\n",
+ " return a, b, c, d, rest\n",
+ "\n",
+ "\n",
+ "fun(*[1, 2], 3, *range(4, 7))"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 9,
- "metadata": {},
+ "execution_count": 33,
"outputs": [
{
"data": {
- "text/plain": [
- "[('black', 'S'),\n",
- " ('black', 'M'),\n",
- " ('black', 'L'),\n",
- " ('white', 'S'),\n",
- " ('white', 'M'),\n",
- " ('white', 'L')]"
- ]
+ "text/plain": "(0, 1, 2, 3, 4)"
},
- "execution_count": 9,
+ "execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "shirts = [(color, size) for size in sizes\n",
- " for color in colors]\n",
- "tshirts"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Example 2-5. Initializing a tuple and an array from a generator expression"
- ]
+ "*range(4), 4"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 10,
- "metadata": {},
+ "execution_count": 34,
"outputs": [
{
"data": {
- "text/plain": [
- "(36, 162, 163, 165, 8364, 164)"
- ]
+ "text/plain": "[0, 1, 2, 3, 4]"
},
- "execution_count": 10,
+ "execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "symbols = '$¢£¥€¤'\n",
- "tuple(ord(symbol) for symbol in symbols)"
- ]
+ "[*range(4), 4]"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 11,
- "metadata": {},
+ "execution_count": 35,
"outputs": [
{
"data": {
- "text/plain": [
- "array('I', [36, 162, 163, 165, 8364, 164])"
- ]
+ "text/plain": "{0, 1, 2, 3, 4, 5, 6, 7}"
},
- "execution_count": 11,
+ "execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "import array\n",
- "array.array('I', (ord(symbol) for symbol in symbols))"
- ]
+ "{*range(4), 4, *(5, 6, 7)}"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "markdown",
- "metadata": {},
"source": [
- "#### Example 2-6. Cartesian product in a generator expression"
- ]
+ "### Nested unpacking\n",
+ "#### Example 2-8. Unpacking nested tuples to access the longitude\n",
+ "\n",
+ "[02-array-seq/metro_lat_lon.py](02-array-seq/metro_lat_lon.py)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Pattern Matching with Sequences\n",
+ "#### Example 2-9. Method from an imaginary Robot class"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 12,
- "metadata": {},
+ "execution_count": 36,
+ "outputs": [],
+ "source": [
+ "# def handle_command(self, message):\n",
+ "# match message:\n",
+ "# case ['BEEPER', frequency, times]:\n",
+ "# self.beep(times, frequency)\n",
+ "# case ['NECK', angle]:\n",
+ "# self.rotate_neck(angle)\n",
+ "# case ['LED', ident, intensity]:\n",
+ "# self.leds[ident].set_brightness(ident, intensity)\n",
+ "# case ['LED', ident, red, green, blue]:\n",
+ "# self.leds[ident].set_color(ident, red, green, blue)\n",
+ "# case _:\n",
+ "# raise InvalidCommand(message)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "#### Example 2-10. Destructuring nested tuples—requires Python ≥ 3.10.\n",
+ "[02-array-seq/match_lat_lon.py](02-array-seq/match_lat_lon.py)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "black S\n",
- "black M\n",
- "black L\n",
- "white S\n",
- "white M\n",
- "white L\n"
+ " | latitude | longitude\n",
+ "Mexico City | 19.4333 | -99.1333\n",
+ "New York-Newark | 40.8086 | -74.0204\n",
+ "São Paulo | -23.5478 | -46.6358\n"
]
}
],
"source": [
- "colors = ['black', 'white']\n",
- "sizes = ['S', 'M', 'L']\n",
+ "metro_areas = [\n",
+ " ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),\n",
+ " ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),\n",
+ " ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),\n",
+ " ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),\n",
+ " ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),\n",
+ "]\n",
"\n",
- "for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):\n",
- " print(tshirt)"
- ]
+ "def main():\n",
+ " print(f'{\"\":15} | {\"latitude\":>9} | {\"longitude\":>9}')\n",
+ " for record in metro_areas:\n",
+ " match record:\n",
+ " case [name, _, _, (lat, lon)] if lon <= 0:\n",
+ " print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')\n",
+ "main()"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "### Pattern Matching Sequences in an Interpreter\n",
+ "#### Example 2-11. Matching patterns without match/case.\n",
+ "[02-array-seq/lispy/py3.9/lis.py](02-array-seq/lispy/py3.9/lis.py)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "#### Example 2-12. Pattern matching with match/case—requires Python ≥ 3.10.\n",
+ "[02-array-seq/lispy/py3.10/lis.py](02-array-seq/lispy/py3.10/lis.py)"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [],
+ "metadata": {
+ "collapsed": false
+ }
},
{
"cell_type": "markdown",
@@ -375,16 +1137,14 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[10, 20]"
- ]
+ "text/plain": "[10, 20]"
},
- "execution_count": 13,
+ "execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
@@ -397,16 +1157,14 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[30, 40, 50, 60]"
- ]
+ "text/plain": "[30, 40, 50, 60]"
},
- "execution_count": 14,
+ "execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
@@ -417,16 +1175,14 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[10, 20, 30]"
- ]
+ "text/plain": "[10, 20, 30]"
},
- "execution_count": 15,
+ "execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
@@ -437,16 +1193,14 @@
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[40, 50, 60]"
- ]
+ "text/plain": "[40, 50, 60]"
},
- "execution_count": 16,
+ "execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
@@ -464,16 +1218,14 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "'bye'"
- ]
+ "text/plain": "'bye'"
},
- "execution_count": 17,
+ "execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
@@ -485,16 +1237,14 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "'elcycib'"
- ]
+ "text/plain": "'elcycib'"
},
- "execution_count": 18,
+ "execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
@@ -505,16 +1255,14 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "'eccb'"
- ]
+ "text/plain": "'eccb'"
},
- "execution_count": 19,
+ "execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
@@ -527,12 +1275,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-9. Line items from a flat-file invoice"
+ "#### Example 2-13. Line items from a flat-file invoice"
]
},
{
"cell_type": "code",
- "execution_count": 20,
+ "execution_count": 45,
"metadata": {},
"outputs": [
{
@@ -577,16 +1325,14 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
- ]
+ "text/plain": "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
},
- "execution_count": 21,
+ "execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
@@ -598,16 +1344,14 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 47,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, 1, 20, 30, 5, 6, 7, 8, 9]"
- ]
+ "text/plain": "[0, 1, 20, 30, 5, 6, 7, 8, 9]"
},
- "execution_count": 22,
+ "execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
@@ -619,16 +1363,14 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 48,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, 1, 20, 30, 5, 8, 9]"
- ]
+ "text/plain": "[0, 1, 20, 30, 5, 8, 9]"
},
- "execution_count": 23,
+ "execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
@@ -640,16 +1382,14 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, 1, 20, 11, 5, 22, 9]"
- ]
+ "text/plain": "[0, 1, 20, 11, 5, 22, 9]"
},
- "execution_count": 24,
+ "execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
@@ -668,7 +1408,7 @@
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 50,
"metadata": {},
"outputs": [
{
@@ -688,16 +1428,14 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, 1, 100, 22, 9]"
- ]
+ "text/plain": "[0, 1, 100, 22, 9]"
},
- "execution_count": 26,
+ "execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
@@ -711,21 +1449,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Using + and * with Sequences"
+ "## Using + and * with Sequences"
]
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 52,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]"
- ]
+ "text/plain": "[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]"
},
- "execution_count": 27,
+ "execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
@@ -737,16 +1473,14 @@
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "'abcdabcdabcdabcdabcd'"
- ]
+ "text/plain": "'abcdabcdabcdabcdabcd'"
},
- "execution_count": 28,
+ "execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
@@ -766,21 +1500,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-10. A list with three lists of length 3 can represent a tic-tac-toe board"
+ "#### Example 2-14. A list with three lists of length 3 can represent a tic-tac-toe board"
]
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 54,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
- ]
+ "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
},
- "execution_count": 29,
+ "execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
@@ -792,16 +1524,14 @@
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 55,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]"
- ]
+ "text/plain": "[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]"
},
- "execution_count": 30,
+ "execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
@@ -815,21 +1545,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-11. A list with three references to the same list is useless"
+ "#### Example 2-15. A list with three references to the same list is useless"
]
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 56,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
- ]
+ "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
},
- "execution_count": 31,
+ "execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
@@ -841,16 +1569,14 @@
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]"
- ]
+ "text/plain": "[['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]"
},
- "execution_count": 32,
+ "execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
@@ -869,16 +1595,14 @@
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
- ]
+ "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]"
},
- "execution_count": 33,
+ "execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
@@ -893,16 +1617,14 @@
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 59,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[['_', '_', '_'], ['_', '_', '_'], ['X', '_', '_']]"
- ]
+ "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['X', '_', '_']]"
},
- "execution_count": 34,
+ "execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
@@ -921,7 +1643,7 @@
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
@@ -931,16 +1653,14 @@
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "4414271936"
- ]
+ "text/plain": "140694277263808"
},
- "execution_count": 36,
+ "execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
@@ -952,16 +1672,14 @@
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[1, 2, 3, 1, 2, 3]"
- ]
+ "text/plain": "[1, 2, 3, 1, 2, 3]"
},
- "execution_count": 37,
+ "execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
@@ -973,16 +1691,14 @@
},
{
"cell_type": "code",
- "execution_count": 38,
+ "execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "True"
- ]
+ "text/plain": "True"
},
- "execution_count": 38,
+ "execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
@@ -993,7 +1709,7 @@
},
{
"cell_type": "code",
- "execution_count": 39,
+ "execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
@@ -1003,16 +1719,14 @@
},
{
"cell_type": "code",
- "execution_count": 40,
+ "execution_count": 65,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "4414275328"
- ]
+ "text/plain": "140694329335488"
},
- "execution_count": 40,
+ "execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
@@ -1024,35 +1738,34 @@
},
{
"cell_type": "code",
- "execution_count": 41,
+ "execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "False"
- ]
+ "text/plain": "False"
},
- "execution_count": 41,
+ "execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t *= 2\n",
- "id(t) == idt # new tuple"
+ "id(t) == idt # new tuple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "### A += Assignment Puzzler"
+ "### A += Assignment Puzzler\n",
+ "#### Example 2-16. A riddle"
]
},
{
"cell_type": "code",
- "execution_count": 42,
+ "execution_count": 67,
"metadata": {},
"outputs": [
{
@@ -1071,18 +1784,28 @@
" print(repr(e))"
]
},
+ {
+ "cell_type": "markdown",
+ "source": [
+ "#### Example 2-17. The unexpected result: item t2 is changed and an exception is raised"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
+ },
{
"cell_type": "code",
- "execution_count": 43,
+ "execution_count": 68,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "(1, 2, [30, 40, 50, 60])"
- ]
+ "text/plain": "(1, 2, [30, 40, 50, 60])"
},
- "execution_count": 43,
+ "execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
@@ -1095,12 +1818,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-14. Bytecode for the expression s[a] += b"
+ "#### Example 2-18. Bytecode for the expression s[a] += b"
]
},
{
"cell_type": "code",
- "execution_count": 44,
+ "execution_count": 69,
"metadata": {},
"outputs": [
{
@@ -1135,16 +1858,14 @@
},
{
"cell_type": "code",
- "execution_count": 45,
+ "execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['apple', 'banana', 'grape', 'raspberry']"
- ]
+ "text/plain": "['apple', 'banana', 'grape', 'raspberry']"
},
- "execution_count": 45,
+ "execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
@@ -1156,16 +1877,14 @@
},
{
"cell_type": "code",
- "execution_count": 46,
+ "execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['grape', 'raspberry', 'apple', 'banana']"
- ]
+ "text/plain": "['grape', 'raspberry', 'apple', 'banana']"
},
- "execution_count": 46,
+ "execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
@@ -1176,16 +1895,14 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['raspberry', 'grape', 'banana', 'apple']"
- ]
+ "text/plain": "['raspberry', 'grape', 'banana', 'apple']"
},
- "execution_count": 47,
+ "execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
@@ -1196,16 +1913,14 @@
},
{
"cell_type": "code",
- "execution_count": 48,
+ "execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['grape', 'apple', 'banana', 'raspberry']"
- ]
+ "text/plain": "['grape', 'apple', 'banana', 'raspberry']"
},
- "execution_count": 48,
+ "execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
@@ -1216,16 +1931,14 @@
},
{
"cell_type": "code",
- "execution_count": 49,
+ "execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['raspberry', 'banana', 'grape', 'apple']"
- ]
+ "text/plain": "['raspberry', 'banana', 'grape', 'apple']"
},
- "execution_count": 49,
+ "execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
@@ -1236,16 +1949,14 @@
},
{
"cell_type": "code",
- "execution_count": 50,
+ "execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['grape', 'raspberry', 'apple', 'banana']"
- ]
+ "text/plain": "['grape', 'raspberry', 'apple', 'banana']"
},
- "execution_count": 50,
+ "execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
@@ -1256,16 +1967,14 @@
},
{
"cell_type": "code",
- "execution_count": 51,
+ "execution_count": 76,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['apple', 'banana', 'grape', 'raspberry']"
- ]
+ "text/plain": "['apple', 'banana', 'grape', 'raspberry']"
},
- "execution_count": 51,
+ "execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
@@ -1279,322 +1988,231 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Managing Ordered Sequences with bisect"
+ "## When a List Is Not the Answer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-15. bisect finds insertion points for items in a sorted sequence"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "DEMO: bisect_right\n",
- "haystack -> 1 4 5 6 8 12 15 20 21 23 23 26 29 30\n",
- "31 @ 14 | | | | | | | | | | | | | |31\n",
- "30 @ 14 | | | | | | | | | | | | | |30\n",
- "29 @ 13 | | | | | | | | | | | | |29\n",
- "23 @ 11 | | | | | | | | | | |23\n",
- "22 @ 9 | | | | | | | | |22\n",
- "10 @ 5 | | | | |10\n",
- " 8 @ 5 | | | | |8 \n",
- " 5 @ 3 | | |5 \n",
- " 2 @ 1 |2 \n",
- " 1 @ 1 |1 \n",
- " 0 @ 0 0 \n"
- ]
- }
- ],
- "source": [
- "# BEGIN BISECT_DEMO\n",
- "import bisect\n",
- "import sys\n",
- "\n",
- "HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]\n",
- "NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]\n",
- "\n",
- "ROW_FMT = '{0:2d} @ {1:2d} {2}{0:<2d}'\n",
- "\n",
- "def demo(haystack, needles, bisect_fn):\n",
- " print('DEMO:', bisect_fn.__name__) # <1>\n",
- " print('haystack ->', ' '.join('%2d' % n for n in haystack))\n",
- " for needle in reversed(needles):\n",
- " position = bisect_fn(haystack, needle) # <2>\n",
- " offset = position * ' |' # <3>\n",
- " print(ROW_FMT.format(needle, position, offset)) # <4>\n",
- "\n",
- "demo(HAYSTACK, NEEDLES, bisect.bisect) # <5>\n",
- "# END BISECT_DEMO"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 53,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "DEMO: bisect_left\n",
- "haystack -> 1 4 5 6 8 12 15 20 21 23 23 26 29 30\n",
- "31 @ 14 | | | | | | | | | | | | | |31\n",
- "30 @ 13 | | | | | | | | | | | | |30\n",
- "29 @ 12 | | | | | | | | | | | |29\n",
- "23 @ 9 | | | | | | | | |23\n",
- "22 @ 9 | | | | | | | | |22\n",
- "10 @ 5 | | | | |10\n",
- " 8 @ 4 | | | |8 \n",
- " 5 @ 2 | |5 \n",
- " 2 @ 1 |2 \n",
- " 1 @ 0 1 \n",
- " 0 @ 0 0 \n"
- ]
- }
- ],
- "source": [
- "demo(HAYSTACK, NEEDLES, bisect.bisect_left)"
+ "### Arrays"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-16. Given a test score, grade returns the corresponding letter grade"
+ "#### Example 2-19. Creating, saving, and loading a large array of floats"
]
},
{
"cell_type": "code",
- "execution_count": 54,
+ "execution_count": 77,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['F', 'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A']"
- ]
+ "text/plain": "0.8190492979077034"
},
- "execution_count": 54,
+ "execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):\n",
- " i = bisect.bisect(breakpoints, score)\n",
- " return grades[i]\n",
+ "from array import array\n",
+ "from random import random, seed\n",
+ "seed(10) # Use seed to make the output consistent\n",
"\n",
- "[grade(score) for score in [55, 60, 65, 70, 75, 80, 85, 90, 95]]"
+ "floats = array('d', (random() for i in range(10 ** 7)))\n",
+ "floats[-1]"
]
},
{
- "cell_type": "markdown",
+ "cell_type": "code",
+ "execution_count": 78,
"metadata": {},
+ "outputs": [],
"source": [
- "#### Example 2-17. bisect_left maps a score of 60 to grade F, not D as in Example 2-16."
+ "with open('floats.bin', 'wb') as fp:\n",
+ " floats.tofile(fp)"
]
},
{
"cell_type": "code",
- "execution_count": 55,
+ "execution_count": 79,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "['F', 'F', 'D', 'D', 'C', 'C', 'B', 'B', 'A']"
- ]
+ "text/plain": "0.8190492979077034"
},
- "execution_count": 55,
+ "execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):\n",
- " i = bisect.bisect_left(breakpoints, score)\n",
- " return grades[i]\n",
+ "floats2 = array('d')\n",
"\n",
- "[grade(score) for score in [55, 60, 65, 70, 75, 80, 85, 90, 95]]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Example 2-18. Insort keeps a sorted sequence always sorted"
+ "with open('floats.bin', 'rb') as fp:\n",
+ " floats2.fromfile(fp, 10 ** 7)\n",
+ "\n",
+ "floats2[-1]"
]
},
{
"cell_type": "code",
- "execution_count": 56,
+ "execution_count": 80,
"metadata": {},
"outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "insert 10 -> [10]\n",
- "insert 0 -> [0, 10]\n",
- "insert 6 -> [0, 6, 10]\n",
- "insert 8 -> [0, 6, 8, 10]\n",
- "insert 7 -> [0, 6, 7, 8, 10]\n",
- "insert 2 -> [0, 2, 6, 7, 8, 10]\n",
- "insert 10 -> [0, 2, 6, 7, 8, 10, 10]\n"
- ]
+ "data": {
+ "text/plain": "True"
+ },
+ "execution_count": 80,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "import bisect\n",
- "import random\n",
- "\n",
- "SIZE = 7\n",
- "\n",
- "random.seed(1729)\n",
- "\n",
- "my_list = []\n",
- "\n",
- "for i in range(SIZE):\n",
- " new_item = random.randrange(SIZE*2)\n",
- " bisect.insort(my_list, new_item)\n",
- " print(f'insert {new_item:2d} -> {my_list}')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## When a List Is Not the Answer"
+ "floats2 == floats"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Arrays"
+ "### Memory Views"
]
},
{
"cell_type": "markdown",
- "metadata": {},
"source": [
- "#### Example 2-19. Creating, saving, and loading a large array of floats"
- ]
+ "#### Example 2-20. Handling 6 bytes memory of as 1×6, 2×3, and 3×2 views"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%% md\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 57,
- "metadata": {},
+ "execution_count": 81,
"outputs": [
{
"data": {
- "text/plain": [
- "0.5963321947530882"
- ]
+ "text/plain": "[0, 1, 2, 3, 4, 5]"
},
- "execution_count": 57,
+ "execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "from array import array\n",
- "from random import random\n",
- "\n",
- "floats = array('d', (random() for i in range(10**7)))\n",
- "floats[-1]"
- ]
+ "octets = array('B', range(6))\n",
+ "m1 = memoryview(octets)\n",
+ "m1.tolist()"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 58,
- "metadata": {},
- "outputs": [],
+ "execution_count": 82,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": "[[0, 1, 2], [3, 4, 5]]"
+ },
+ "execution_count": 82,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "with open('floats.bin', 'wb') as fp:\n",
- " floats.tofile(fp)"
- ]
+ "m2 = m1.cast('B', [2, 3])\n",
+ "m2.tolist()"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 59,
- "metadata": {},
+ "execution_count": 83,
"outputs": [
{
"data": {
- "text/plain": [
- "0.5963321947530882"
- ]
+ "text/plain": "[[0, 1], [2, 3], [4, 5]]"
},
- "execution_count": 59,
+ "execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "floats2 = array('d')\n",
- "\n",
- "with open('floats.bin', 'rb') as fp:\n",
- " floats2.fromfile(fp, 10**7)\n",
- "\n",
- "floats2[-1]"
- ]
+ "m3 = m1.cast('B', [3, 2])\n",
+ "m3.tolist()"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 60,
- "metadata": {},
+ "execution_count": 84,
"outputs": [
{
"data": {
- "text/plain": [
- "True"
- ]
+ "text/plain": "array('B', [0, 1, 2, 33, 22, 5])"
},
- "execution_count": 60,
+ "execution_count": 84,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "floats2 == floats"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Memory Views"
- ]
+ "m2[1,1] = 22\n",
+ "m3[1,1] = 33\n",
+ "octets"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-20. Changing the value of an array item by poking one of its bytes"
+ "#### Example 2-21. Changing the value of an 16-bit integer array item by poking one of its bytes"
]
},
{
"cell_type": "code",
- "execution_count": 61,
+ "execution_count": 85,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "5"
- ]
+ "text/plain": "5"
},
- "execution_count": 61,
+ "execution_count": 85,
"metadata": {},
"output_type": "execute_result"
}
@@ -1607,16 +2225,14 @@
},
{
"cell_type": "code",
- "execution_count": 62,
+ "execution_count": 86,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "-2"
- ]
+ "text/plain": "-2"
},
- "execution_count": 62,
+ "execution_count": 86,
"metadata": {},
"output_type": "execute_result"
}
@@ -1627,16 +2243,14 @@
},
{
"cell_type": "code",
- "execution_count": 63,
+ "execution_count": 87,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]"
- ]
+ "text/plain": "[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]"
},
- "execution_count": 63,
+ "execution_count": 87,
"metadata": {},
"output_type": "execute_result"
}
@@ -1648,16 +2262,14 @@
},
{
"cell_type": "code",
- "execution_count": 64,
+ "execution_count": 88,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array('h', [-2, -1, 1024, 1, 2])"
- ]
+ "text/plain": "array('h', [-2, -1, 1024, 1, 2])"
},
- "execution_count": 64,
+ "execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
@@ -1671,50 +2283,47 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### NumPy and SciPy"
+ "### NumPy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-21. Basic operations with rows and columns in a numpy.ndarray"
+ "#### Example 2-22. Basic operations with rows and columns in a numpy.ndarray"
]
},
{
"cell_type": "code",
- "execution_count": 65,
+ "execution_count": 89,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])"
- ]
+ "text/plain": "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])"
},
- "execution_count": 65,
+ "execution_count": 89,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
+ "\n",
"a = np.arange(12)\n",
"a"
]
},
{
"cell_type": "code",
- "execution_count": 66,
+ "execution_count": 90,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "numpy.ndarray"
- ]
+ "text/plain": "numpy.ndarray"
},
- "execution_count": 66,
+ "execution_count": 90,
"metadata": {},
"output_type": "execute_result"
}
@@ -1725,16 +2334,14 @@
},
{
"cell_type": "code",
- "execution_count": 67,
+ "execution_count": 91,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "(12,)"
- ]
+ "text/plain": "(12,)"
},
- "execution_count": 67,
+ "execution_count": 91,
"metadata": {},
"output_type": "execute_result"
}
@@ -1745,18 +2352,14 @@
},
{
"cell_type": "code",
- "execution_count": 68,
+ "execution_count": 92,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([[ 0, 1, 2, 3],\n",
- " [ 4, 5, 6, 7],\n",
- " [ 8, 9, 10, 11]])"
- ]
+ "text/plain": "array([[ 0, 1, 2, 3],\n [ 4, 5, 6, 7],\n [ 8, 9, 10, 11]])"
},
- "execution_count": 68,
+ "execution_count": 92,
"metadata": {},
"output_type": "execute_result"
}
@@ -1768,16 +2371,14 @@
},
{
"cell_type": "code",
- "execution_count": 69,
+ "execution_count": 93,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([ 8, 9, 10, 11])"
- ]
+ "text/plain": "array([ 8, 9, 10, 11])"
},
- "execution_count": 69,
+ "execution_count": 93,
"metadata": {},
"output_type": "execute_result"
}
@@ -1788,16 +2389,14 @@
},
{
"cell_type": "code",
- "execution_count": 70,
+ "execution_count": 94,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "9"
- ]
+ "text/plain": "9"
},
- "execution_count": 70,
+ "execution_count": 94,
"metadata": {},
"output_type": "execute_result"
}
@@ -1808,16 +2407,14 @@
},
{
"cell_type": "code",
- "execution_count": 71,
+ "execution_count": 95,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([1, 5, 9])"
- ]
+ "text/plain": "array([1, 5, 9])"
},
- "execution_count": 71,
+ "execution_count": 95,
"metadata": {},
"output_type": "execute_result"
}
@@ -1828,25 +2425,20 @@
},
{
"cell_type": "code",
- "execution_count": 72,
+ "execution_count": 96,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([[ 0, 4, 8],\n",
- " [ 1, 5, 9],\n",
- " [ 2, 6, 10],\n",
- " [ 3, 7, 11]])"
- ]
+ "text/plain": "array([[ 0, 4, 8],\n [ 1, 5, 9],\n [ 2, 6, 10],\n [ 3, 7, 11]])"
},
- "execution_count": 72,
+ "execution_count": 96,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "a.transpose()\n"
+ "a.transpose()"
]
},
{
@@ -1858,7 +2450,7 @@
},
{
"cell_type": "code",
- "execution_count": 73,
+ "execution_count": 97,
"metadata": {},
"outputs": [],
"source": [
@@ -1869,7 +2461,7 @@
},
{
"cell_type": "code",
- "execution_count": 74,
+ "execution_count": 98,
"metadata": {},
"outputs": [],
"source": [
@@ -1878,16 +2470,14 @@
},
{
"cell_type": "code",
- "execution_count": 75,
+ "execution_count": 99,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([0.29150425, 0.33893554, 0.08112756])"
- ]
+ "text/plain": "array([0.06078257, 0.61741189, 0.84349987])"
},
- "execution_count": 75,
+ "execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
@@ -1898,16 +2488,14 @@
},
{
"cell_type": "code",
- "execution_count": 76,
+ "execution_count": 100,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "array([0.14575213, 0.16946777, 0.04056378])"
- ]
+ "text/plain": "array([0.03039128, 0.30870594, 0.42174994])"
},
- "execution_count": 76,
+ "execution_count": 100,
"metadata": {},
"output_type": "execute_result"
}
@@ -1919,16 +2507,14 @@
},
{
"cell_type": "code",
- "execution_count": 77,
+ "execution_count": 101,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "True"
- ]
+ "text/plain": "True"
},
- "execution_count": 77,
+ "execution_count": 101,
"metadata": {},
"output_type": "execute_result"
}
@@ -1943,7 +2529,7 @@
},
{
"cell_type": "code",
- "execution_count": 78,
+ "execution_count": 102,
"metadata": {},
"outputs": [],
"source": [
@@ -1954,16 +2540,14 @@
},
{
"cell_type": "code",
- "execution_count": 79,
+ "execution_count": 103,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "memmap([0.29150425, 0.33893554, 0.08112756])"
- ]
+ "text/plain": "memmap([0.06078257, 0.61741189, 0.84349987])"
},
- "execution_count": 79,
+ "execution_count": 103,
"metadata": {},
"output_type": "execute_result"
}
@@ -1983,21 +2567,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#### Example 2-22. Working with a deque"
+ "#### Example 2-23. Working with a deque"
]
},
{
"cell_type": "code",
- "execution_count": 80,
+ "execution_count": 104,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
- ]
+ "text/plain": "deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
},
- "execution_count": 80,
+ "execution_count": 104,
"metadata": {},
"output_type": "execute_result"
}
@@ -2011,16 +2593,14 @@
},
{
"cell_type": "code",
- "execution_count": 81,
+ "execution_count": 105,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6])"
- ]
+ "text/plain": "deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6])"
},
- "execution_count": 81,
+ "execution_count": 105,
"metadata": {},
"output_type": "execute_result"
}
@@ -2032,16 +2612,14 @@
},
{
"cell_type": "code",
- "execution_count": 82,
+ "execution_count": 106,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])"
- ]
+ "text/plain": "deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])"
},
- "execution_count": 82,
+ "execution_count": 106,
"metadata": {},
"output_type": "execute_result"
}
@@ -2053,16 +2631,14 @@
},
{
"cell_type": "code",
- "execution_count": 83,
+ "execution_count": 107,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
- ]
+ "text/plain": "deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
},
- "execution_count": 83,
+ "execution_count": 107,
"metadata": {},
"output_type": "execute_result"
}
@@ -2074,16 +2650,14 @@
},
{
"cell_type": "code",
- "execution_count": 84,
+ "execution_count": 108,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33])"
- ]
+ "text/plain": "deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33])"
},
- "execution_count": 84,
+ "execution_count": 108,
"metadata": {},
"output_type": "execute_result"
}
@@ -2095,16 +2669,14 @@
},
{
"cell_type": "code",
- "execution_count": 85,
+ "execution_count": 109,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8])"
- ]
+ "text/plain": "deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8])"
},
- "execution_count": 85,
+ "execution_count": 109,
"metadata": {},
"output_type": "execute_result"
}
@@ -2130,7 +2702,7 @@
},
{
"cell_type": "code",
- "execution_count": 86,
+ "execution_count": 110,
"metadata": {},
"outputs": [],
"source": [
@@ -2139,7 +2711,7 @@
},
{
"cell_type": "code",
- "execution_count": 87,
+ "execution_count": 111,
"metadata": {},
"outputs": [
{
@@ -2166,16 +2738,14 @@
},
{
"cell_type": "code",
- "execution_count": 88,
+ "execution_count": 112,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, '1', 5, 6, '9', 14, 19, '23', 28, '28']"
- ]
+ "text/plain": "[0, '1', 5, 6, '9', 14, 19, '23', 28, '28']"
},
- "execution_count": 88,
+ "execution_count": 112,
"metadata": {},
"output_type": "execute_result"
}
@@ -2188,16 +2758,14 @@
},
{
"cell_type": "code",
- "execution_count": 89,
+ "execution_count": 113,
"metadata": {},
"outputs": [
{
"data": {
- "text/plain": [
- "[0, '1', 14, 19, '23', 28, '28', 5, 6, '9']"
- ]
+ "text/plain": "[0, '1', 14, 19, '23', 28, '28', 5, 6, '9']"
},
- "execution_count": 89,
+ "execution_count": 113,
"metadata": {},
"output_type": "execute_result"
}
@@ -2208,7 +2776,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 113,
"metadata": {},
"outputs": [],
"source": []
@@ -2235,4 +2803,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
-}
+}
\ No newline at end of file
diff --git a/02-array-seq/test.sh b/02-array-seq/test.sh
index 4747320..906717d 100755
--- a/02-array-seq/test.sh
+++ b/02-array-seq/test.sh
@@ -1,4 +1,4 @@
#!/bin/bash
python3 -m doctest bisect_demo.py
-python3 -m doctest metro_lat_long.py
+python3 -m doctest metro_lat_lon.py
pytest -q --nbval
diff --git a/06-obj-ref/README.rst b/06-obj-ref/README.rst
index deac2fa..0d705e6 100644
--- a/06-obj-ref/README.rst
+++ b/06-obj-ref/README.rst
@@ -1,4 +1,4 @@
-Sample code for Chapter 8 - "Object references, mutability and recycling"
+Sample code for Chapter 6 - "Object references, mutability and recycling"
From the book "Fluent Python" by Luciano Ramalho (O'Reilly, 2015)
http://shop.oreilly.com/product/0636920032519.do
diff --git a/08-def-type-hints/callable/variance.py b/08-def-type-hints/callable/variance.py
new file mode 100644
index 0000000..fcddbde
--- /dev/null
+++ b/08-def-type-hints/callable/variance.py
@@ -0,0 +1,22 @@
+from collections.abc import Callable
+
+def update( # <1>
+ probe: Callable[[], float], # <2>
+ display: Callable[[float], None] # <3>
+ ) -> None:
+ temperature = probe()
+ # imagine lots of control code here
+ display(temperature)
+
+def probe_ok() -> int: # <4>
+ return 42
+
+def display_wrong(temperature: int) -> None: # <5>
+ print(hex(temperature))
+
+update(probe_ok, display_wrong) # type error # <6>
+
+def display_ok(temperature: complex) -> None: # <7>
+ print(temperature)
+
+update(probe_ok, display_ok) # OK # <8>
diff --git a/08-def-type-hints/coordinates/requirements.txt b/08-def-type-hints/coordinates/requirements.txt
index fb11094..7b7b424 100644
--- a/08-def-type-hints/coordinates/requirements.txt
+++ b/08-def-type-hints/coordinates/requirements.txt
@@ -1,2 +1,2 @@
geolib==1.0.7
-future==0.18.2
+future==0.18.3
diff --git a/17-it-generator/columnize_iter.py b/17-it-generator/columnize_iter.py
index cee0f13..4362bc1 100644
--- a/17-it-generator/columnize_iter.py
+++ b/17-it-generator/columnize_iter.py
@@ -6,8 +6,8 @@ def columnize(
) -> Iterator[tuple[str, ...]]: # <1>
if num_columns == 0:
num_columns = round(len(sequence) ** 0.5)
- num_rows, reminder = divmod(len(sequence), num_columns)
- num_rows += bool(reminder)
+ num_rows, remainder = divmod(len(sequence), num_columns)
+ num_rows += bool(remainder)
return (tuple(sequence[i::num_rows]) for i in range(num_rows)) # <2>
# end::COLUMNIZE[]
diff --git a/20-executors/getflags/flags2_asyncio.py b/20-executors/getflags/flags2_asyncio.py
index 4f1849a..b697840 100755
--- a/20-executors/getflags/flags2_asyncio.py
+++ b/20-executors/getflags/flags2_asyncio.py
@@ -79,6 +79,8 @@ async def supervisor(cc_list: list[str],
error = exc # <10>
except KeyboardInterrupt:
break
+ else:
+ error = None
if error:
status = DownloadStatus.ERROR # <11>
diff --git a/20-executors/getflags/requirements.txt b/20-executors/getflags/requirements.txt
index b8bb630..9b1faeb 100644
--- a/20-executors/getflags/requirements.txt
+++ b/20-executors/getflags/requirements.txt
@@ -1,10 +1,10 @@
anyio==3.3.2
-certifi==2021.5.30
+certifi==2024.7.4
charset-normalizer==2.0.6
-h11==0.12.0
+h11==0.16.0
httpcore==0.13.7
httpx==1.0.0b0
-idna==3.2
+idna==3.7
rfc3986==1.5.0
sniffio==1.2.0
-tqdm==4.62.3
+tqdm==4.66.3
diff --git a/21-async/mojifinder/requirements.txt b/21-async/mojifinder/requirements.txt
index 1f7c3d6..6831fee 100644
--- a/21-async/mojifinder/requirements.txt
+++ b/21-async/mojifinder/requirements.txt
@@ -1,7 +1,7 @@
click==7.1.2
fastapi==0.65.2
-h11==0.12.0
-pydantic==1.8.2
-starlette==0.13.6
+h11==0.16.0
+pydantic==1.10.13
+starlette==0.40.0
typing-extensions==3.7.4.3
uvicorn==0.13.4
diff --git a/README.md b/README.md
index 96273ac..234c8da 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,7 @@
# Fluent Python 2e example code
-Example code for the book **Fluent Python, 2nd edition** by Luciano Ramalho (O'Reilly, 2021).
+Example code for the book **Fluent Python, Second Edition** by Luciano Ramalho (O'Reilly, 2022).
-> **BEWARE**: This is a work in progress!
->
-> * Code here may change and disappear without warning.
->
-> * Major reorganizations may happen at any time.
->
-> * No promises. No guarantees. Use at own risk.
## Table of Contents
@@ -16,37 +9,37 @@ All chapters are undergoing review and updates, including significant rewrites i
New chapters in **Fluent Python 2e** are marked with 🆕.
-🚨 This table of contents is subject to change at any time until the book goes to the printer.
+> 🚨 This table of contents is subject to change at any time until the book goes to the printer.
+Latest change: Old **Part I—Prologue** merged into new **Part I—Data Structures**; parts renumbered accordingly; chapter numbers unchanged.
Part / Chapter #|Title|Directory|1st ed. Chapter #
---:|---|---|:---:
-**I – Prologue**|
+**I – Data Structures**|
1|The Python Data Model|[01-data-model](01-data-model)|1
-**II – Data Structures**|
2|An Array of Sequences|[02-array-seq](02-array-seq)|2
3|Dictionaries and Sets|[03-dict-set](03-dict-set)|3
4|Unicode Text versus Bytes|[04-text-byte](04-text-byte)|4
5|Data Class Builders|[05-data-classes](05-data-classes)|🆕
6|Object References, Mutability, and Recycling|[06-obj-ref](06-obj-ref)|8
-**III – Functions as Objects**|
+**II – Functions as Objects**|
7|Funcions as First-Class Objects|[07-1class-func](07-1class-func)|5
-8|Type Hints in Function Definitions|[08-def-type-hints](08-def-type-hints)|🆕
-9|Function Decorators and Closures|[09-closure-deco](09-closure-deco)|7
+8|Type Hints in Functions|[08-def-type-hints](08-def-type-hints)|🆕
+9|Decorators and Closures|[09-closure-deco](09-closure-deco)|7
10|Design Patterns with First-Class Functions|[10-dp-1class-func](10-dp-1class-func)|6
-**IV – Object-Oriented Idioms**|
+**III – Object-Oriented Idioms**|
11|A Pythonic Object|[11-pythonic-obj](11-pythonic-obj)|9
-12|Sequence Hacking, Hashing, and Slicing|[12-seq-hacking](12-seq-hacking)|10
+12|Special Methods for Sequences|[12-seq-hacking](12-seq-hacking)|10
13|Interfaces, Protocols, and ABCs|[13-protocl-abc](13-protocol-abc)|11
-14|Inheritance: For Good or For Worse|[14-inheritance](14-inheritance)|12
+14|Inheritance: For Better or For Worse|[14-inheritance](14-inheritance)|12
15|More About Type Hints|[15-more-types](15-more-types)|🆕
-16|Operator Overloading: Doing It Right|[16-op-overloading](16-op-overloading)|13
-**V – Control Flow**|
+16|Operator Overloading|[16-op-overloading](16-op-overloading)|13
+**IV – Control Flow**|
17|Iterators, Generators, and Classic Coroutines|[17-it-generator](17-it-generator)|14
-18|Context Managers and else Blocks|[18-with-match](18-with-match)|15
+18|with, match, and else Blocks|[18-with-match](18-with-match)|15
19|Concurrency Models in Python|[19-concurrency](19-concurrency)|🆕
20|Concurrent Executors|[20-executors](20-executors)|17
21|Asynchronous Programming|[21-async](21-async)|18
-**VI – Metaprogramming**|
+**V – Metaprogramming**|
22|Dynamic Attributes and Properties|[22-dyn-attr-prop](22-dyn-attr-prop)|19
23|Attribute Descriptors|[23-descriptor](23-descriptor)|20
24|Class Metaprogramming|[24-class-metaprog](24-class-metaprog)|21
diff --git a/links/FPY.LI.htaccess b/links/FPY.LI.htaccess
index 6e324d0..5607fa4 100644
--- a/links/FPY.LI.htaccess
+++ b/links/FPY.LI.htaccess
@@ -1,3 +1,6 @@
+# to recreate or update this file:
+# $ cat custom.htaccess short.htaccess > FPY.LI.htaccess
+
ErrorDocument 404 /404.html
# main resources
@@ -35,6 +38,9 @@ RedirectTemp /typecoro https://docs.python.org/3.10/library/typing.html#typing.C
RedirectTemp /typing https://docs.python.org/3/library/typing.html
RedirectTemp /weakref https://www.fluentpython.com/extra/weak-references/
+# URL added during QA of the Second Edition
+RedirectTemp /bdfl https://www.artima.com/weblogs/viewpost.jsp?thread=235725
+
# Python Enhancement Proposals
RedirectTemp /pep218 https://www.python.org/dev/peps/pep-0218/
RedirectTemp /pep227 https://www.python.org/dev/peps/pep-0227/
@@ -149,7 +155,7 @@ RedirectTemp /a-18 https://www.python.org/doc/essays/
RedirectTemp /1-1 http://hugunin.net/story_of_jython.html
RedirectTemp /1-2 https://www.oreilly.com/library/view/jython-essentials/9781449397364/
RedirectTemp /1-3 https://docs.python.org/3/reference/lexical_analysis.html#reserved-classes-of-identifiers
-RedirectTemp /1-4 https://docs.python.org/2/library/string.html#format-string-syntax
+RedirectTemp /1-4 https://docs.python.org/3.10/library/string.html#format-string-syntax
RedirectTemp /1-5 https://stackoverflow.com/questions/1436703/what-is-the-difference-between-str-and-repr
RedirectTemp /1-6 https://docs.python.org/3/library/stdtypes.html#truth
RedirectTemp /1-7 https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists
@@ -1067,3 +1073,17 @@ RedirectTemp /24-27 https://docs.python.org/3/library/functools.html#functools.t
RedirectTemp /24-28 https://www.python.org/download/releases/2.2.3/descrintro/
RedirectTemp /24-29 https://github.com/lihaoyi/macropy
RedirectTemp /24-30 https://people.eecs.berkeley.edu/~bh/ss-toc2.html
+# content of short.htaccess file created and managed by short.py
+
+# appended: 2025-05-23 15:12:13
+RedirectTemp /22 https://pythonfluente.com/2/#pattern_matching_case_study_sec
+RedirectTemp /23 https://pythonfluente.com/2/#how_slicing_works
+RedirectTemp /24 https://pythonfluente.com/2/#sliceable_sequence
+RedirectTemp /25 https://pythonfluente.com/2/#virtual_subclass_sec
+RedirectTemp /26 https://pythonfluente.com/2/#environment_class_ex
+RedirectTemp /27 https://pythonfluente.com/2/#subclass_builtin_woes
+RedirectTemp /28 https://pythonfluente.com/2/#slots_section
+RedirectTemp /29 https://pythonfluente.com/2/#typeddict_sec
+RedirectTemp /2a https://pythonfluente.com/2/#problems_annot_runtime_sec
+RedirectTemp /2b https://pythonfluente.com/2/#legacy_deprecated_typing_box
+RedirectTemp /2c https://pythonfluente.com/2/#positional_pattern_implement_sec
diff --git a/links/README.md b/links/README.md
index 09c808a..65749b2 100644
--- a/links/README.md
+++ b/links/README.md
@@ -1,37 +1,6 @@
-# Short links for URLs in the book
+This file is deployed as `.htaccess` to the FPY.LI domain
+to map short URLs in Fluent Python to the original URLs.
-## Problem: link rot
+To update it, I use tools in this other repo:
-_Fluent Python, Second Edition_ has more than 1000 links to external resources.
-Inevitably, some of those links will rot as time passes.
-But I can't change the URLs in the print book...
-
-## Solution: indirection
-
-I replaced almost all URLs in the book with shortened versions that go through the `fpy.li` site which I control.
-The site has an `.htaccess` file with *temporary* redirects.
-
-When I find out a link is stale, I can thange the redirect in `.htaccess` to a new target,
-so the link in the book is back in service through the updated redirect.
-
-## Help wanted
-
-Please report broken links as bugs in the [`FPY.LI.htaccess`](FPY.LI.htaccess) file.
-Also, feel free to send pull requests with fixes to that file.
-When I accept a PR, I will redeploy it to `fpy.li/.htaccess`.
-
-## Details
-
-Almost all URLs in the book are replaced with shortened versions like
-[`http://fpy.li/1-3`](http://fpy.li/1-3)—for chapter 1, link #3.
-
-There are also custom short URLs like
-[`https://fpy.li/code`](https://fpy.li/code) which redirects to the example code repository.
-I used custom short URLs for URLs with 3 or more mentions, or links to PEPs.
-
-Exceptions:
-
-- URLs with `oreilly` in them are unchanged;
-- `fluentpython.com` URL (with no path) is unchanged;
-
-The `FPY.LI.htaccess` is deployed at the root folder in `http://fpy.li`.
+https://github.com/pythonfluente/pythonfluente2e
diff --git a/links/custom.htaccess b/links/custom.htaccess
deleted file mode 100644
index a13b9f8..0000000
--- a/links/custom.htaccess
+++ /dev/null
@@ -1,113 +0,0 @@
-ErrorDocument 404 /404.html
-
-# main resources
-RedirectTemp /book https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/
-RedirectTemp /code https://github.com/fluentpython/example-code-2e
-RedirectTemp /home https://www.fluentpython.com/
-
-# URLs mentioned at least three times
-RedirectTemp /bisect https://www.fluentpython.com/extra/ordered-sequences-with-bisect/
-RedirectTemp /cardxvi https://www.python.org/dev/peps/pep-0484/#the-numeric-tower
-RedirectTemp /collec https://docs.python.org/3/library/collections.html
-RedirectTemp /dask https://dask.org/
-RedirectTemp /dtmodel https://docs.python.org/3/reference/datamodel.html
-RedirectTemp /descr101 https://www.python.org/download/releases/2.2.3/descrintro/
-RedirectTemp /descrhow https://docs.python.org/3/howto/descriptor.html
-RedirectTemp /doctest https://docs.python.org/3/library/doctest.html
-RedirectTemp /effectpy https://effectivepython.com/
-RedirectTemp /fmtspec https://docs.python.org/3/library/string.html#formatspec
-RedirectTemp /gunicorn https://gunicorn.org/
-RedirectTemp /hashint https://www.fluentpython.com/extra/internals-of-sets-and-dicts/
-RedirectTemp /hattingh https://www.oreilly.com/library/view/using-asyncio-in/9781492075325/
-RedirectTemp /httpx https://www.python-httpx.org/
-RedirectTemp /initvar https://docs.python.org/3/library/dataclasses.html#init-only-variables
-RedirectTemp /mypy https://mypy.readthedocs.io/en/stable/
-RedirectTemp /norvigdp http://norvig.com/design-patterns/
-RedirectTemp /nsphere https://en.wikipedia.org/wiki/N-sphere
-RedirectTemp /oldcoro https://www.fluentpython.com/extra/classic-coroutines/
-RedirectTemp /pandas https://pandas.pydata.org/
-RedirectTemp /pycook3 https://www.oreilly.com/library/view/python-cookbook-3rd/9781449357337/
-RedirectTemp /pynut3 https://www.oreilly.com/library/view/python-in-a/9781491913833/
-RedirectTemp /pypydif https://doc.pypy.org/en/latest/cpython_differences.html#subclasses-of-built-in-types
-RedirectTemp /shed4051 https://github.com/python/typeshed/issues/4051
-RedirectTemp /specattr https://docs.python.org/3/library/stdtypes.html#special-attributes
-RedirectTemp /typecoro https://docs.python.org/3.10/library/typing.html#typing.Coroutine
-RedirectTemp /typing https://docs.python.org/3/library/typing.html
-RedirectTemp /weakref https://www.fluentpython.com/extra/weak-references/
-
-# Python Enhancement Proposals
-RedirectTemp /pep218 https://www.python.org/dev/peps/pep-0218/
-RedirectTemp /pep227 https://www.python.org/dev/peps/pep-0227/
-RedirectTemp /pep255 https://www.python.org/dev/peps/pep-0255/
-RedirectTemp /pep342 https://www.python.org/dev/peps/pep-0342/
-RedirectTemp /pep343 https://www.python.org/dev/peps/pep-0343/
-RedirectTemp /pep357 https://www.python.org/dev/peps/pep-0357/
-RedirectTemp /pep362 https://www.python.org/dev/peps/pep-0362/
-RedirectTemp /pep371 https://www.python.org/dev/peps/pep-0371/
-RedirectTemp /pep380 https://www.python.org/dev/peps/pep-0380/
-RedirectTemp /pep393 https://www.python.org/dev/peps/pep-0393/
-RedirectTemp /pep412 https://www.python.org/dev/peps/pep-0412/
-RedirectTemp /pep442 https://www.python.org/dev/peps/pep-0442/
-RedirectTemp /pep443 https://www.python.org/dev/peps/pep-0443/
-RedirectTemp /pep448 https://www.python.org/dev/peps/pep-0448/
-RedirectTemp /pep455 https://www.python.org/dev/peps/pep-0455/
-RedirectTemp /pep456 https://www.python.org/dev/peps/pep-0456/
-RedirectTemp /pep461 https://www.python.org/dev/peps/pep-0461/
-RedirectTemp /pep465 https://www.python.org/dev/peps/pep-0465/
-RedirectTemp /pep467 https://www.python.org/dev/peps/pep-0467/
-RedirectTemp /pep482 https://www.python.org/dev/peps/pep-0482/
-RedirectTemp /pep483 https://www.python.org/dev/peps/pep-0483/
-RedirectTemp /pep484 https://www.python.org/dev/peps/pep-0484/
-RedirectTemp /pep487 https://www.python.org/dev/peps/pep-0487/
-RedirectTemp /pep492 https://www.python.org/dev/peps/pep-0492/
-RedirectTemp /pep519 https://www.python.org/dev/peps/pep-0519/
-RedirectTemp /pep525 https://www.python.org/dev/peps/pep-0525/
-RedirectTemp /pep526 https://www.python.org/dev/peps/pep-0526/
-RedirectTemp /pep528 https://www.python.org/dev/peps/pep-0528/
-RedirectTemp /pep529 https://www.python.org/dev/peps/pep-0529/
-RedirectTemp /pep530 https://www.python.org/dev/peps/pep-0530/
-RedirectTemp /pep544 https://www.python.org/dev/peps/pep-0544/
-RedirectTemp /pep554 https://www.python.org/dev/peps/pep-0554/
-RedirectTemp /pep557 https://www.python.org/dev/peps/pep-0557/
-RedirectTemp /pep560 https://www.python.org/dev/peps/pep-0560/
-RedirectTemp /pep561 https://www.python.org/dev/peps/pep-0561/
-RedirectTemp /pep563 https://www.python.org/dev/peps/pep-0563/
-RedirectTemp /pep570 https://www.python.org/dev/peps/pep-0570/
-RedirectTemp /pep572 https://www.python.org/dev/peps/pep-0572/
-RedirectTemp /pep584 https://www.python.org/dev/peps/pep-0584/
-RedirectTemp /pep585 https://www.python.org/dev/peps/pep-0585/
-RedirectTemp /pep586 https://www.python.org/dev/peps/pep-0586/
-RedirectTemp /pep589 https://www.python.org/dev/peps/pep-0589/
-RedirectTemp /pep591 https://www.python.org/dev/peps/pep-0591/
-RedirectTemp /pep593 https://www.python.org/dev/peps/pep-0593/
-RedirectTemp /pep604 https://www.python.org/dev/peps/pep-0604/
-RedirectTemp /pep612 https://www.python.org/dev/peps/pep-0612/
-RedirectTemp /pep613 https://www.python.org/dev/peps/pep-0613/
-RedirectTemp /pep616 https://www.python.org/dev/peps/pep-0616/
-RedirectTemp /pep617 https://www.python.org/dev/peps/pep-0617/
-RedirectTemp /pep618 https://www.python.org/dev/peps/pep-0618/
-RedirectTemp /pep634 https://www.python.org/dev/peps/pep-0634/
-RedirectTemp /pep635 https://www.python.org/dev/peps/pep-0635/
-RedirectTemp /pep636 https://www.python.org/dev/peps/pep-0636/
-RedirectTemp /pep638 https://www.python.org/dev/peps/pep-0638/
-RedirectTemp /pep645 https://www.python.org/dev/peps/pep-0645/
-RedirectTemp /pep646 https://www.python.org/dev/peps/pep-0646/
-RedirectTemp /pep647 https://www.python.org/dev/peps/pep-0647/
-RedirectTemp /pep649 https://www.python.org/dev/peps/pep-0649/
-RedirectTemp /pep654 https://www.python.org/dev/peps/pep-0654/
-RedirectTemp /pep655 https://www.python.org/dev/peps/pep-0655/
-RedirectTemp /pep661 https://www.python.org/dev/peps/pep-0661/
-RedirectTemp /pep3099 https://www.python.org/dev/peps/pep-3099/
-RedirectTemp /pep3102 https://www.python.org/dev/peps/pep-3102/
-RedirectTemp /pep3104 https://www.python.org/dev/peps/pep-3104/
-RedirectTemp /pep3106 https://www.python.org/dev/peps/pep-3106/
-RedirectTemp /pep3107 https://www.python.org/dev/peps/pep-3107/
-RedirectTemp /pep3115 https://www.python.org/dev/peps/pep-3115/
-RedirectTemp /pep3118 https://www.python.org/dev/peps/pep-3118/
-RedirectTemp /pep3119 https://www.python.org/dev/peps/pep-3119/
-RedirectTemp /pep3129 https://www.python.org/dev/peps/pep-3129/
-RedirectTemp /pep3132 https://www.python.org/dev/peps/pep-3132/
-RedirectTemp /pep3141 https://www.python.org/dev/peps/pep-3141/
-RedirectTemp /pep3148 https://www.python.org/dev/peps/pep-3148/
-RedirectTemp /pep3155 https://www.python.org/dev/peps/pep-3155/
-RedirectTemp /pep3333 https://www.python.org/dev/peps/pep-3333/
diff --git a/ruff.toml b/ruff.toml
new file mode 100644
index 0000000..f7b07e2
--- /dev/null
+++ b/ruff.toml
@@ -0,0 +1,4 @@
+line-length = 100
+[format]
+# Like Python's repr(), use single quotes for strings.
+quote-style = "single"
\ No newline at end of file