{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Chapter 2 An Array of Sequences\n",
"\n",
"**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",
"* [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",
"* [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",
"* [Soapbox](#Soapbox)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## List Comprehensions and Generator Expressions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Example 2-1. Build a list of Unicode codepoints from a string"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": "[36, 162, 163, 165, 8364, 164]"
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"symbols = '$'\n",
"codes = []\n",
"\n",
"for symbol in symbols:\n",
" codes.append(ord(symbol))\n",
"\n",
"codes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Example 2-2. Build a list of Unicode codepoints from a string, using a listcomp"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": "[36, 162, 163, 165, 8364, 164]"
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"symbols = '$'\n",
"\n",
"codes = [ord(symbol) for symbol in symbols]\n",
"\n",
"codes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Box: Listcomps No Longer Leak Their Variables"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": "'ABC'"
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = 'ABC'\n",
"codes = [ord(x) for x in x]\n",
"x"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": "[65, 66, 67]"
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"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": {},
"source": [
"#### Example 2-3. The same list built by a listcomp and a map/filter composition"
]
},
{
"cell_type": "code",
"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": "(0, 1, [])"
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a, b, *rest = range(2)\n",
"a, b, rest"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 30,
"outputs": [
{
"data": {
"text/plain": "(0, [1, 2], 3, 4)"
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a, *body, c, d = range(5)\n",
"a, body, c, d"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 31,
"outputs": [
{
"data": {
"text/plain": "([0, 1], 2, 3, 4)"
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"*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": 32,
"outputs": [
{
"data": {
"text/plain": "(1, 2, 3, 4, (5, 6))"
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"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": 33,
"outputs": [
{
"data": {
"text/plain": "(0, 1, 2, 3, 4)"
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"*range(4), 4"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 34,
"outputs": [
{
"data": {
"text/plain": "[0, 1, 2, 3, 4]"
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[*range(4), 4]"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "code",
"execution_count": 35,
"outputs": [
{
"data": {
"text/plain": "{0, 1, 2, 3, 4, 5, 6, 7}"
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{*range(4), 4, *(5, 6, 7)}"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
},
{
"cell_type": "markdown",
"source": [
"### 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": 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 tuplesrequires 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": [
" | latitude | longitude\n",
"Mexico City | 19.4333 | -99.1333\n",
"New York-Newark | 40.8086 | -74.0204\n",
"So Paulo | -23.5478 | -46.6358\n"
]
}
],
"source": [
"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",
" ('So Paulo', 'BR', 19.649, (-23.547778, -46.635833)),\n",
"]\n",
"\n",
"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