X Tutup
{ "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 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": [ " | 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": [ "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", "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", "metadata": {}, "source": [ "## Slicing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Why Slices and Range Exclude the Last Item" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": "[10, 20]" }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [10, 20, 30, 40, 50, 60]\n", "\n", "l[:2] # split at 2" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": "[30, 40, 50, 60]" }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[2:]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": "[10, 20, 30]" }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[:3] # split at 3" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": "[40, 50, 60]" }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[3:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Slice Objects" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": "'bye'" }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = 'bicycle'\n", "s[::3]" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": "'elcycib'" }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[::-1]" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": "'eccb'" }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[::-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-13. Line items from a flat-file invoice" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " $17.50 imoroni PiBrella \n", " $4.95 mm Tactile Switch x20 \n", " $28.00 anavise Jr. - PV-201 \n", " $34.95 iTFT Mini Kit 320x240 \n", " \n" ] } ], "source": [ "invoice = \"\"\"\n", "0.....6.................................40........52...55........\n", "1909 Pimoroni PiBrella $17.50 3 $52.50\n", "1489 6mm Tactile Switch x20 $4.95 2 $9.90\n", "1510 Panavise Jr. - PV-201 $28.00 1 $28.00\n", "1601 PiTFT Mini Kit 320x240 $34.95 1 $34.95\n", "\"\"\"\n", "\n", "SKU = slice(0, 6)\n", "DESCRIPTION = slice(6, 40)\n", "UNIT_PRICE = slice(40, 52)\n", "QUANTITY = slice(52, 55)\n", "ITEM_TOTAL = slice(55, None)\n", "\n", "line_items = invoice.split('\\n')[2:]\n", "\n", "for item in line_items:\n", " print(item[UNIT_PRICE], item[DESCRIPTION])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Assigning to Slices" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = list(range(10))\n", "l" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, 1, 20, 30, 5, 6, 7, 8, 9]" }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[2:5] = [20, 30]\n", "l" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, 1, 20, 30, 5, 8, 9]" }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "del l[5:7]\n", "l" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, 1, 20, 11, 5, 22, 9]" }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[3::2] = [11, 22]\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By design, this example raises an exception::" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TypeError('can only assign an iterable')\n" ] } ], "source": [ "try:\n", " l[2:5] = 100\n", "except TypeError as e:\n", " print(repr(e))" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, 1, 100, 22, 9]" }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[2:5] = [100]\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using + and * with Sequences" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": "[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]" }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [1, 2, 3]\n", "l * 5" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": "'abcdabcdabcdabcdabcd'" }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 * 'abcd'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Building Lists of Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-14. A list with three lists of length 3 can represent a tic-tac-toe board" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]" }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board = [['_'] * 3 for i in range(3)]\n", "board" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]" }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board[1][2] = 'X'\n", "board" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-15. A list with three references to the same list is useless" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]" }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "weird_board = [['_'] * 3] * 3\n", "weird_board" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]" }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "weird_board[1][2] = 'O'\n", "weird_board" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Explanation" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]" }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board = []\n", "for i in range(3):\n", " row = ['_'] * 3\n", " board.append(row)\n", "board" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": "[['_', '_', '_'], ['_', '_', '_'], ['X', '_', '_']]" }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board[2][0] = 'X'\n", "board" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Augmented Assignment with Sequences" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "l = [1, 2, 3]\n", "idl = id(l)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": "140694277263808" }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# NBVAL_IGNORE_OUTPUT\n", "idl" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": "[1, 2, 3, 1, 2, 3]" }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l *= 2\n", "l" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": "True" }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "id(l) == idl # same list" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "t = (1, 2, 3)\n", "idt = id(t)" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": "140694329335488" }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# NBVAL_IGNORE_OUTPUT\n", "idt" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": "False" }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t *= 2\n", "id(t) == idt # new tuple" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A += Assignment Puzzler\n", "#### Example 2-16. A riddle" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TypeError(\"'tuple' object does not support item assignment\")\n" ] } ], "source": [ "t = (1, 2, [30, 40])\n", "try:\n", " t[2] += [50, 60]\n", "except TypeError as e:\n", " 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": 68, "metadata": {}, "outputs": [ { "data": { "text/plain": "(1, 2, [30, 40, 50, 60])" }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-18. Bytecode for the expression s[a] += b" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 1 0 LOAD_NAME 0 (s)\n", " 2 LOAD_NAME 1 (a)\n", " 4 DUP_TOP_TWO\n", " 6 BINARY_SUBSCR\n", " 8 LOAD_NAME 2 (b)\n", " 10 INPLACE_ADD\n", " 12 ROT_THREE\n", " 14 STORE_SUBSCR\n", " 16 LOAD_CONST 0 (None)\n", " 18 RETURN_VALUE\n" ] } ], "source": [ "import dis\n", "\n", "dis.dis('s[a] += b')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## list.sort and the sorted Built-In Function" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": "['apple', 'banana', 'grape', 'raspberry']" }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fruits = ['grape', 'raspberry', 'apple', 'banana']\n", "sorted(fruits)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": "['grape', 'raspberry', 'apple', 'banana']" }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fruits" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": "['raspberry', 'grape', 'banana', 'apple']" }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(fruits, reverse=True)" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/plain": "['grape', 'apple', 'banana', 'raspberry']" }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(fruits, key=len)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/plain": "['raspberry', 'banana', 'grape', 'apple']" }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(fruits, key=len, reverse=True)" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/plain": "['grape', 'raspberry', 'apple', 'banana']" }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fruits" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/plain": "['apple', 'banana', 'grape', 'raspberry']" }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fruits.sort()\n", "fruits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## When a List Is Not the Answer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-19. Creating, saving, and loading a large array of floats" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/plain": "0.8190492979077034" }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from array import array\n", "from random import random, seed\n", "seed(10) # Use seed to make the output consistent\n", "\n", "floats = array('d', (random() for i in range(10 ** 7)))\n", "floats[-1]" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "with open('floats.bin', 'wb') as fp:\n", " floats.tofile(fp)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/plain": "0.8190492979077034" }, "execution_count": 79, "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]" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/plain": "True" }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "floats2 == floats" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Memory Views" ] }, { "cell_type": "markdown", "source": [ "#### 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": 81, "outputs": [ { "data": { "text/plain": "[0, 1, 2, 3, 4, 5]" }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "octets = array('B', range(6))\n", "m1 = memoryview(octets)\n", "m1.tolist()" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 82, "outputs": [ { "data": { "text/plain": "[[0, 1, 2], [3, 4, 5]]" }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m2 = m1.cast('B', [2, 3])\n", "m2.tolist()" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 83, "outputs": [ { "data": { "text/plain": "[[0, 1], [2, 3], [4, 5]]" }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m3 = m1.cast('B', [3, 2])\n", "m3.tolist()" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 84, "outputs": [ { "data": { "text/plain": "array('B', [0, 1, 2, 33, 22, 5])" }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m2[1,1] = 22\n", "m3[1,1] = 33\n", "octets" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-21. Changing the value of an 16-bit integer array item by poking one of its bytes" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": "5" }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "numbers = array('h', [-2, -1, 0, 1, 2])\n", "memv = memoryview(numbers)\n", "len(memv)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": "-2" }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "memv[0]" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/plain": "[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]" }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "memv_oct = memv.cast('B')\n", "memv_oct.tolist()" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/plain": "array('h', [-2, -1, 1024, 1, 2])" }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "memv_oct[5] = 4\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### NumPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-22. Basic operations with rows and columns in a numpy.ndarray" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" }, "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": 90, "metadata": {}, "outputs": [ { "data": { "text/plain": "numpy.ndarray" }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(a)" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/plain": "(12,)" }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.shape" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([[ 0, 1, 2, 3],\n [ 4, 5, 6, 7],\n [ 8, 9, 10, 11]])" }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.shape = 3, 4\n", "a" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([ 8, 9, 10, 11])" }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[2]" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/plain": "9" }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[2, 1]" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([1, 5, 9])" }, "execution_count": 95, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[:, 1]" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([[ 0, 4, 8],\n [ 1, 5, 9],\n [ 2, 6, 10],\n [ 3, 7, 11]])" }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.transpose()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-22. Loading, saving, and vectorized operations" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [], "source": [ "with open('floats-1M-lines.txt', 'wt') as fp:\n", " for _ in range(1_000_000):\n", " fp.write(f'{random()}\\n')" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [], "source": [ "floats = np.loadtxt('floats-1M-lines.txt')" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([0.06078257, 0.61741189, 0.84349987])" }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "floats[-3:]" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "data": { "text/plain": "array([0.03039128, 0.30870594, 0.42174994])" }, "execution_count": 100, "metadata": {}, "output_type": "execute_result" } ], "source": [ "floats *= .5\n", "floats[-3:]" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "data": { "text/plain": "True" }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from time import perf_counter as pc\n", "\n", "t0 = pc()\n", "floats /= 3\n", "(pc() - t0) < 0.01" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [], "source": [ "np.save('floats-1M', floats)\n", "floats2 = np.load('floats-1M.npy', 'r+')\n", "floats2 *= 6" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [ { "data": { "text/plain": "memmap([0.06078257, 0.61741189, 0.84349987])" }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "floats2[-3:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Deques and Other Queues" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example 2-23. Working with a deque" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import collections\n", "\n", "dq = collections.deque(range(10), maxlen=10)\n", "dq" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6])" }, "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dq.rotate(3)\n", "dq" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])" }, "execution_count": 106, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dq.rotate(-4)\n", "dq" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9])" }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dq.appendleft(-1)\n", "dq" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33])" }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dq.extend([11, 22, 33])\n", "dq" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/plain": "deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8])" }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dq.extendleft([10, 20, 30, 40])\n", "dq" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Soapbox" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mixed bag lists" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [], "source": [ "l = [28, 14, '28', 5, '9', '1', 0, 6, '23', 19]" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TypeError(\"'<' not supported between instances of 'str' and 'int'\")\n" ] } ], "source": [ "try:\n", " sorted(l)\n", "except TypeError as e:\n", " print(repr(e))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Key is Brilliant" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, '1', 5, 6, '9', 14, 19, '23', 28, '28']" }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [28, 14, '28', 5, '9', '1', 0, 6, '23', 19]\n", "\n", "sorted(l, key=int)" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "text/plain": "[0, '1', 14, 19, '23', 28, '28', 5, 6, '9']" }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sorted(l, key=str)" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.0" } }, "nbformat": 4, "nbformat_minor": 2 }
X Tutup