
    
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
            
        
        
        
        
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/twitter-threads","feed_url":"https:\/\/mathspp.com\/blog\/twitter-threads.json","description":"Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com.","author":{"name":"Rodrigo Gir\u00e3o Serr\u00e3o"},"items":[{"title":"4 useful Python command line switches","date_published":"2022-09-05T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/4-useful-python-command-line-switches","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/4-useful-python-command-line-switches","content_html":"<p>This short article teaches you 4 common switches to use in the command line with Python.<\/p>\n\n<p>The Python \ud83d\udc0d command has many different switches.<\/p>\n<p>Here are the 4 switches I use the most:<\/p>\n<ol>\n<li><code>-c cmd<\/code>: program passed in as string;<\/li>\n<li><code>-m mod<\/code>: run library module as a script;<\/li>\n<li><code>-i<\/code>: inspect interactively after running script; and<\/li>\n<li><code>-q<\/code>: don't print version and copyright messages on interactive startup.<\/li>\n<\/ol>\n<h2 id=\"c\"><code>-c<\/code><a href=\"#c\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The switch <code>-c<\/code> runs code directly from the command line.\nIt doesn't open the REPL, and it is convenient for short, one-off expressions.\nThe result isn't printed by default, so don't forget your <code>print<\/code>!<\/p>\n<pre><code># What is the factorial of 15?\n\u03bb python -c \"import math; print(math.factorial(15))\"\n1307674368000\n\n# What is 2 + 2?\n\u03bb python -c \"print(2 + 2)\"\n4<\/code><\/pre>\n<h2 id=\"m\"><code>-m<\/code><a href=\"#m\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The switch <code>-m<\/code> runs a module as a script.\nThis will run an installed module's section that is inside <code>if __name__ == \"__main__\":<\/code>.\nThe one I use the most is the module <code>timeit<\/code> to measure execution time:<\/p>\n<pre><code class=\"language-bash\">\u03bb python -m timeit -s \"import math\" \"math.factorial(15)\"\n2000000 loops, best of 5: 167 nsec per loop\n\n\u03bb python -m timeit -s \"import math\" \"math.factorial(150)\"\n200000 loops, best of 5: 1.52 usec per loop<\/code><\/pre>\n<h2 id=\"i\"><code>-i<\/code><a href=\"#i\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The switch <code>-i<\/code> stands for Inspect Interactively.\nBy running your code with <code>-i<\/code>, after the script is done,\nyou get a REPL session with the variables and functions from that script.\nUseful to play around with functions you just defined.<\/p>\n<p>Suppose this is your file <code>example.py<\/code>:<\/p>\n<pre><code class=\"language-py\">x = 3\ny = 5\n\ndef add(x, y):\n    return x + y<\/code><\/pre>\n<p>If you run it with <code>-i<\/code>, you get to play around with the variables <code>x<\/code> and <code>y<\/code> and with the function <code>add<\/code>:<\/p>\n<pre><code class=\"language-bash\">\u03bb python -i example.py\n&gt;&gt;&gt; x\n3\n&gt;&gt;&gt; y\n5\n&gt;&gt;&gt; add(x, 10)\n13<\/code><\/pre>\n<h2 id=\"q\"><code>-q<\/code><a href=\"#q\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The switch <code>-q<\/code> opens the REPL Quietly.\nWhat this means is that it opens the REPL without displaying all the version\/platform information.\nI use it when recording videos and demoing things.<\/p>\n<pre><code class=\"language-bash\">\u03bb python -q\n&gt;&gt;&gt; # This is a standard REPL<\/code><\/pre>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1566777236035870720\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article teaches you 4 common switches to use in the command line with Python.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"3 different ways to create a dictionary","date_published":"2022-08-26T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/3-different-ways-to-create-a-dictionary","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/3-different-ways-to-create-a-dictionary","content_html":"<p>This short article teaches you 3 ways of creating a Python dictionary.<\/p>\n\n<p>Here are 3 ways in which you can create a Python \ud83d\udc0d dictionary:\n(Of the three, the last one is the least commonly used.)<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; dict([(1, \"one\"), (2, \"two\")])\n{1: 'one', 2: 'two'}\n\n&gt;&gt;&gt; dict(name=\"Rodrigo\", twitter=\"mathsppblog\")\n{'name': 'Rodrigo', 'twitter': 'mathsppblog'}\n\n&gt;&gt;&gt; dict.fromkeys([\"likes\", \"retweets\"], 0)\n{'likes': 0, 'retweets': 0}<\/code><\/pre>\n<h2 id=\"an-iterable-of-key-value-pairs\">An iterable of key, value pairs<a href=\"#an-iterable-of-key-value-pairs\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The built-in <code>dict<\/code> can take an iterable with key, value pairs.\nUseful, for example, when you have a bunch of keys and a bunch of values that you put together with <code>zip<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; dict([(1, \"one\"), (2, \"two\")])\n{1: 'one', 2: 'two'}\n\n&gt;&gt;&gt; keys = range(1, 4)\n&gt;&gt;&gt; values = \"one two three\".split()\n&gt;&gt;&gt; dict(zip(keys, values))\n{1: 'one', 2: 'two', 3: 'three'}<\/code><\/pre>\n<p>In this particular case, you could also get creating with <code>enumerate<\/code>\nand <a href=\"\/blog\/pydonts\/enumerate-me#optional-start-argument\">make use of the keyword argument <code>start<\/code><\/a>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; dict(enumerate(values, start=1))\n{1: 'one', 2: 'two', 3: 'three'}<\/code><\/pre>\n<h2 id=\"keyword-arguments\">Keyword arguments<a href=\"#keyword-arguments\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>You can use keyword arguments in <code>dict<\/code> to define key, value pairs in your dictionary!\nHowever, this only works if your keys are valid variable names:<\/p>\n<pre><code class=\"language-py\"># Values don't have to be strings:\n&gt;&gt;&gt; dict(one=1, two=2)\n{'one': 1, 'two': 2}\n\n# But the keys have to:\n&gt;&gt;&gt; dict(1=\"one\", 2=\"two\")\n  File \"&lt;stdin&gt;\", line 1\n    dict(1=\"one\", 2=\"two\")\n         ^\nSyntaxError: expression cannot contain assignment, perhaps you meant \"==\"?\n\n# Keys have to be valid variable names:\n&gt;&gt;&gt; dict(name=\"Rodrigo\", twitter=\"mathsppblog\")\n{'name': 'Rodrigo', 'twitter': 'mathsppblog'}<\/code><\/pre>\n<h2 id=\"class-method-dict-fromkeys\">Class method <code>dict.fromkeys<\/code><a href=\"#class-method-dict-fromkeys\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The class method <code>dict.fromkeys<\/code> accepts an iterable and a value, and produces a dictionary where all keys have that value.\nBy default, that value is <code>None<\/code>:<\/p>\n<pre><code class=\"language-py\"># Default value is None:\n&gt;&gt;&gt; dict.fromkeys(\"abc\")\n{'a': None, 'b': None, 'c': None}\n&gt;&gt;&gt; dict.fromkeys(range(5))\n{0: None, 1: None, 2: None, 3: None, 4: None}\n\n# Different default values:\n&gt;&gt;&gt; dict.fromkeys(range(5), \";)\")\n{0: ';)', 1: ';)', 2: ';)', 3: ';)', 4: ';)'}\n&gt;&gt;&gt; dict.fromkeys([\"likes\", \"retweets\"], 0)\n{'likes': 0, 'retweets': 0}<\/code><\/pre>\n<p>The class method <code>.fromkeys<\/code> has a gotcha associated with it, though.\nBe careful when using mutable values, because the value isn't copied to each key.\nIt's exactly the same object used over and over:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; d = dict.fromkeys(range(3), [])\n&gt;&gt;&gt; d\n{0: [], 1: [], 2: []}\n\n&gt;&gt;&gt; d[0].append(\"zero\")\n&gt;&gt;&gt; d[1].append(\"one\")\n\n&gt;&gt;&gt; d[2]  # Shouldn't d[2] be empty?!\n['zero', 'one']\n&gt;&gt;&gt; d\n{0: ['zero', 'one'], 1: ['zero', 'one'], 2: ['zero', 'one']}  # \ud83e\udd2f<\/code><\/pre>\n<p>These are just 3 ways of creating a Python dictionary.\nSoon, I'll send out a Mathspp Insider article talking about all the ways in which you can create dictionaries in Python \ud83d\udc0d\nJoin to keep learning: <a href=\"https:\/\/mathspp.com\/insider\">https:\/\/mathspp.com\/insider<\/a><\/p>\n<h2 id=\"summary\">Summary<a href=\"#summary\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Here's a quick recap:<\/p>\n<ol>\n<li><code>dict<\/code> accepts an iterable that contains key, value pairs;<\/li>\n<li>use keyword arguments in <code>dict<\/code> if you want string keys; and<\/li>\n<li><code>.fromkeys<\/code> gives the same value (default is <code>None<\/code>) to a bunch of keys.<\/li>\n<\/ol>\n<p>Comment other ways in which you can create a Python \ud83d\udc0d dict!<\/p>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1563153357359181824\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article teaches you 3 ways of creating a Python dictionary.","date_modified":"2025-09-27T16:50:04+02:00","tags":["programming","python"]},{"title":"3 ways to reverse a Python list","date_published":"2022-08-25T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/3-ways-to-reverse-a-python-list","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/3-ways-to-reverse-a-python-list","content_html":"<p>This short article teaches you 3 ways of reversing a Python list.<\/p>\n\n<p>Here are 3 simple ways in which you can reverse a Python \ud83d\udc0d list:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst = [42, 73, 0]\n&gt;&gt;&gt; rev1 = reversed(lst)\n&gt;&gt;&gt; rev2 = lst[::-1]\n&gt;&gt;&gt; lst.reverse()<\/code><\/pre>\n<p>Let's see how they are different.<\/p>\n<h2 id=\"built-in-reversed\">Built-in <code>reversed<\/code><a href=\"#built-in-reversed\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The built-in <code>reversed<\/code> accepts a sequence and returns an object that knows how to iterate over that sequence in reverse order.\nHence, <code>reversed<\/code>.\nNotice it doesn't return a list:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; reversed(lst)\n&lt;list_reverseiterator object at 0x00000241D77BD520&gt;<\/code><\/pre>\n<p>The <code>list_reverseiterator<\/code> object that is returned is \u201clinked\u201d to the original list...\nSo, if you change the original list, the reverse iterator will notice:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst = [42, 73, 0]\n&gt;&gt;&gt; rev = reversed(lst)\n&gt;&gt;&gt; lst[1] = 999999  # Change something in the original list.\n\n&gt;&gt;&gt; for n in rev:  # Go over the reverse iterator.\n...     print(n)\n...\n0\n999999  # This was changed as well.\n42<\/code><\/pre>\n<h2 id=\"slicing-with-1\">Slicing with <code>[::-1]<\/code><a href=\"#slicing-with-1\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The slicing syntax with brackets <code>[]<\/code> and colons <code>:<\/code> accepts a \u201cstep\u201d that can be negative.\nIf the \u201cstart\u201d and \u201cstop\u201d are omitted and the \u201cstep\u201d is -1, we get a copy in the reverse order:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst = [42, 73, 0]\n&gt;&gt;&gt; lst[::-1]\n[0, 73, 42]<\/code><\/pre>\n<p>Slices in Python \ud83d\udc0d are regular objects, so you can also name them.\nThus, you could go as far as creating a named slice to reverse lists, and then use it:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst\n[42, 73, 0]\n\n&gt;&gt;&gt; reverse = slice(None, None, -1)\n&gt;&gt;&gt; lst[reverse]\n[0, 73, 42]<\/code><\/pre>\n<p>Notice that slices are not \u201clinked\u201d to the original list.\nThat's because slicing creates a copy of the list.\nSo, if you change the elements in a given index, the reversed list will not notice:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst = [42, 73, 0]  # Original list.\n&gt;&gt;&gt; rev = lst[::-1]    # Reverse copy.\n&gt;&gt;&gt; lst[1] = 999999    # Change something in the original.\n&gt;&gt;&gt; rev                # The copy didn't notice.\n[0, 73, 42]<\/code><\/pre>\n<p>Slicing is very powerful and useful, and that is why I wrote a whole chapter of my <a href=\"https:\/\/mathspp.gumroad.com\/l\/pydonts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">free book \u201cPydon'ts\u201d<\/a> on the subject.<\/p>\n<h2 id=\"list-method-reverse\">List method <code>.reverse<\/code><a href=\"#list-method-reverse\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Lists have a method <code>.reverse<\/code> that reverses the list <strong>in place<\/strong>.\nWhat this means is that you do not get a return value with the reversed list...\nInstead, the list itself gets flipped around \ud83d\ude43<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; lst = [42, 73, 0]\n&gt;&gt;&gt; lst.reverse()\n&gt;&gt;&gt; lst\n[0, 73, 42]<\/code><\/pre>\n<h2 id=\"summary\">Summary<a href=\"#summary\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Here is a quick summary:<\/p>\n<p>Reverse a Python list with:<\/p>\n<ol>\n<li>the built-in <code>reversed<\/code> that will notice changes to the original list;<\/li>\n<li>slicing <code>[::-1]<\/code> that creates a copy of the original list; and<\/li>\n<li>the method <code>.reverse<\/code> that reverses a list in place.<\/li>\n<\/ol>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1562714998757277696\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article teaches you 3 ways of reversing a Python list.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"Deciphering David Beazley&#039;s monstrosity","date_published":"2022-08-22T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/deciphering-david-beazleys-monstrosity","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/deciphering-david-beazleys-monstrosity","content_html":"<p>This short article explains a monstrous piece of code that David Beazley wrote.<\/p>\n\n<p>I just found another Python \ud83d\udc0d monstrosity:<\/p>\n<pre><code class=\"language-py\">sub = lambda x,y,c: c(x-y)\nmul = lambda x,y,c: c(x*y)\neqv = lambda x,y,c: c(x==y)\nbnz = lambda t,c,a: (a,c)[t]()\n\ndef fact(n, c):\n    (loop:= lambda n, r0: (\n            eqv(n, 1, lambda r1:\n            bnz(r1, lambda: c(r0), lambda:\n            mul(n, r0, lambda r2:\n            sub(n, 1, lambda r3:\n            loop(r3, r2)))))))\\\n    (n, 1)\n\nfact(5, print)<\/code><\/pre>\n<p>This one was brought to you by the infamous David Beazley.\nBut what does it do?<\/p>\n<p>Let us start by looking at the four lambdas at the top.<\/p>\n<p>The first three are quite similar to each other:<\/p>\n<pre><code class=\"language-py\">sub = lambda x,y,c: c(x-y)\nmul = lambda x,y,c: c(x*y)\neqv = lambda x,y,c: c(x==y)\nbnz = lambda t,c,a: (a,c)[t]()\n\nsub(5, 3, print)  # Prints 2\nmul(5, 3, print)  # Prints 15\neqv(5, 3, print)  # Prints False<\/code><\/pre>\n<p>Take the first two arguments, operate on them, and recursively call <code>c<\/code> with the result.<\/p>\n<p>So, David is going to chain operations by doing these crazy recursive calls.<\/p>\n<p>The fourth lambda is a bit more interesting but also crazier: it implements conditionals.\n(I have no idea what \u201cbnz\u201d means, though \ud83e\udd37)\nThe first argument is the Boolean value, then:<\/p>\n<ul>\n<li>if the Boolean is <code>True<\/code>, we call <code>c<\/code>;<\/li>\n<li>if it is <code>False<\/code>, we call the alternative <code>a<\/code>.<\/li>\n<\/ul>\n<pre><code class=\"language-py\">bnz = lambda t,c,a: (a,c)[t]()\n\nyes = lambda: print(\"heya\")\nno = lambda: print(\":(\")\n\nbnz(True, yes, no)  # Prints heya\nbnz(False, yes, no)  # Prints :(<\/code><\/pre>\n<p>Alright, we are halfway there!\nNow, we just need to understand how David put everything together to implement the factorial function.<\/p>\n<p>The function <code>fact<\/code> defines <code>loop<\/code> in its body, which is a tail recursive factorial.\nRemember that the 3rd arguments of <code>sub<\/code>, <code>mul<\/code>, and <code>eqv<\/code>, can be seen as what happens after that operation.<\/p>\n<pre><code class=\"language-py\">def fact(n, c):\n    (loop:= lambda n, r0: (  # Start computing with n and r0.\n            eqv(n, 1, lambda r1:  # Is n equal to 1?\n            bnz(r1, lambda: c(r0), lambda:  # If it is, call c(r0) and end, if not...\n            mul(n, r0, lambda r2:  # multiply n with r0 and call it r2, then\n            sub(n, 1, lambda r3:  # compute n - 1 and call it r3, and\n            loop(r3, r2)))))))\\   # go to the top, with the new values for n and r0.\n    (n, 1)<\/code><\/pre>\n<p>In the lambda <code>loop<\/code>, <code>n<\/code> is the value for which we still have to compute the factorial,\nand it decreases with each call.\n<code>r0<\/code> is the accumulated factorial that grows as we reduce the value of <code>n<\/code>.<\/p>\n<p>Does this make sense?<\/p>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1561765223408730116\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article explains a monstrous piece of code that David Beazley wrote.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"Chunking iterables","date_published":"2022-08-17T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/chunking-iterables","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/chunking-iterables","content_html":"<p>This short article shows how to chunk iterables into pieces of a fixed length.<\/p>\n\n<p>If you need to chunk a list or another iterable into groups of <code>n<\/code> items,\nyou can do that with the built-in <code>zip<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; def chunk(iterable, chunk_size):\n...     return list(zip(*[iter(iterable)] * chunk_size))\n...\n&gt;&gt;&gt; chunk(range(10), 5)\n[(0, 1, 2, 3, 4), (5, 6, 7, 8, 9)]<\/code><\/pre>\n<p>You can also add a third argument to process each chunk after it is created:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; chunk(\"Hello, world\", 3)\n[('H', 'e', 'l'), ('l', 'o', ','), (' ', 'w', 'o'), ('r', 'l', 'd')]\n\n# Redefine `chunk`:\n&gt;&gt;&gt; def chunk(iterable, chunk_size, on_chunk=None):\n...     on_chunk = on_chunk or (lambda x: x)\n...     return [on_chunk(chunk) for chunk in zip(*[iter(iterable)] * chunk_size)]\n...\n&gt;&gt;&gt; chunk(\"Hello, world\", 3, \"\".join)\n['Hel', 'lo,', ' wo', 'rld']<\/code><\/pre>\n<p>The code above has a limitation, though:\nit ignores the last elements if the chunk size doesn't divide evenly into the length of the iterable.\nSometimes this is ok... Sometimes, it is not.<\/p>\n<p>If you use <code>itertools.zip_longest<\/code>, you get the opposite behaviour:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; chunk(range(8), 5)\n[(0, 1, 2, 3, 4)]  # where are 5, 6, and 7??\n\n&gt;&gt;&gt; from itertools import zip_longest\n&gt;&gt;&gt; def chunk_longest(iterable, chunk_size):\n...     return list(zip_longest(*[iter(iterable)] * chunk_size))\n...\n\n&gt;&gt;&gt; chunk_longest(range(8), 5)\n[(0, 1, 2, 3, 4), (5, 6, 7, None, None)]<\/code><\/pre>\n<p>By using <code>zip_longest<\/code>, you get padding with the value <code>None<\/code>.\nYou could also customise this padding.<\/p>\n<p>Finally, if you want your chunks to always have the same size, you can use <code>strict=True<\/code> in <code>zip<\/code>!\nThis will make your <code>chunk<\/code> function error if the chunk size doesn't divide evenly!\nHowever, this only works in Python 3.10+ because that is when <code>zip(..., strict=True)<\/code> was added.<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; def chunk_strict(iterable, chunk_size):\n...     return list(zip(*[iter(iterable)] * chunk_size, strict=True))\n...\n\n# 2 divides into 6\n&gt;&gt;&gt; chunk_strict(range(6), 2)\n[(0, 1), (2, 3), (4, 5)]\n\n# 5 does NOT divide into 8\n&gt;&gt;&gt; chunk_strict(range(8), 5)\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\n  File \"&lt;stdin&gt;\", line 2, in chunk_strict\nValueError: zip() argument 4 is shorter than arguments 1-3<\/code><\/pre>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1559837003973287936\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article shows how to chunk iterables into pieces of a fixed length.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"bisect module","date_published":"2022-08-10T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/bisect-module","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/bisect-module","content_html":"<p>This short article shows how to use the module <code>bisect<\/code> from the Python standard library.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<p>Are you familiar with the module <code>bisect<\/code> from the Python \ud83d\udc0d standard library?<\/p>\n<p>It is a small module to help you work with sorted lists.\nIf you have a sorted list and a new value, you can find the index where the new value would go by using the method <code>bisect<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; value = 22\n&gt;&gt;&gt; ordered_values = [1, 5, 19, 23]\n# `value` would go at index 3 -^\n\n&gt;&gt;&gt; import bisect\n&gt;&gt;&gt; bisect.bisect(ordered_values, value)\n3  # the index where `value` would go\n\n&gt;&gt;&gt; ordered_values.insert(3, value)\n&gt;&gt;&gt; ordered_values\n[1, 5, 19, 22, 23]<\/code><\/pre>\n<p>The function <code>bisect<\/code> tells you where a value <em>would<\/em> go...\nBut if you want to insert it, <code>bisect<\/code> can also do that for you!\nJust use the method <code>insort<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; ordered_values\n[1, 5, 19, 22, 23]\n\n# Let's add 21 in there, preserving the order:\n&gt;&gt;&gt; bisect.insort(ordered_values, 21)\n&gt;&gt;&gt; ordered_values\n[1, 5, 19, 21, 22, 23]<\/code><\/pre>\n<p>The module <code>bisect<\/code> has four more methods: <code>bisect_left<\/code>, <code>bisect_right<\/code>, <code>insort_left<\/code>, and <code>insort_right<\/code>...\nThe <code>_left<\/code> and <code>_right<\/code> tell you where to place ties (elements that are equal).<\/p>\n<p>The methods <code>bisect<\/code> and <code>insort<\/code>, shown above, match their <code>_right<\/code> variants.<\/p>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1557367701252734976\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"This short article shows how to use the module `bisect` from the Python standard library.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"Simplifying equality comparisons with or","date_published":"2022-08-05T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/simplifying-equality-comparisons-with-or","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/simplifying-equality-comparisons-with-or","content_html":"<p>In this short article I describe how to simplify equality comparisons chained with the operator <code>or<\/code>.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<p>Do you want to check if a Python \ud83d\udc0d variable matches one of several possible values?\nInstead of writing a big chain of <code>or<\/code> and equalities <code>==<\/code>, use the <code>in<\/code> operator!<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; x = 43\n&gt;&gt;&gt; if x == 42 or x == 43 or x == 44:\n...     print(\"Nice!\")\n...\nNice!\n&gt;&gt;&gt; if x in (42, 43, 44):\n...     print(\"Nice!\")\n...\nNice!<\/code><\/pre>\n<p>Using <code>in<\/code> is a great tip but it isn't always a suitable alternative!\nThe operator <code>or<\/code> short-circuits, which means it stops comparing as soon as it finds a <code>True<\/code>.\nThis isn't the case if you use <code>in<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; def f():\n...     return 42\n...\n&gt;&gt;&gt; def g():\n...     return 43\n...\n&gt;&gt;&gt; def h():\n...     return 1 \/ 0\n...\n&gt;&gt;&gt; if x == f() or x == g() or x == h():\n...     print(\"Nice!\")\n...\nNice!\n&gt;&gt;&gt; if x in (f(), g(), h()):\n...     print(\"Nice!\")\n...\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\n  File \"&lt;stdin&gt;\", line 2, in h\nZeroDivisionError: division by zero<\/code><\/pre>\n<p>You can read more about short-circuiting in <a href=\"\/blog\/pydonts\/boolean-short-circuiting\">this Pydon't article<\/a>.<\/p>\n<p>For a bonus tip, see @guilatrova's tweet on a similar tip:<\/p>\n<blockquote class=\"twitter-tweet\"><p lang=\"en\" dir=\"ltr\">I stumbled on an alternative way of comparing many values in Python. \ud83d\udc0d<br><br>\u2022 Define tuples for a shorter comparison.<br>\u2022 Remove the \"and\" operator<br><br>Which way do you prefer? Why? <a href=\"https:\/\/t.co\/VjZFL8tsQQ\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">pic.twitter.com\/VjZFL8tsQQ<\/a><\/p>\u2014 Gui Latrova (@guilatrova) <a href=\"https:\/\/twitter.com\/guilatrova\/status\/1555508935200686080?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">August 5, 2022<\/a><\/blockquote>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1555527830603239430\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"In this short article I describe how to simplify equality comparisons chained with the operator `or`.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"Conditional expressions in list comprehensions","date_published":"2022-06-30T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/conditional-expressions-in-list-comprehensions","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/conditional-expressions-in-list-comprehensions","content_html":"<p>In this short article I describe how to use conditional expressions in list comprehensions.<\/p>\n\n<p>Conditional expressions in <a href=\"\/blog\/pydonts\/list-comprehensions-101\">list comprehensions<\/a> can be quite powerful because they let us write more flexible comprehensions.<\/p>\n<p>List comprehensions start with an expression that modifies values.\nTypically, you always modify values in the same way, with the same function or formula.\nHowever, sometimes you may want to adapt the modification to the value itself.<\/p>\n<p>Here's an example using the Collatz sequence:<\/p>\n<pre><code class=\"language-py\"># Google for the Collatz conjecture;\n# Take a number n, and do a step:\n# odd numbers go n -&gt; 3 * n + 1\n# even numbers go n -&gt; n \/\/ 2\n\n# Compute 1 step for some initial numbers:\nsteps = []\nfor n in range(100):\n    if n % 2:\n        steps.append(3 * n + 1)\n    else:\n        steps.append(n \/\/ 2)<\/code><\/pre>\n<p>Notice how, in the example above, we always want to append to the final list.\nIt's just that we want to append one of two different things, depending on <code>n % 2<\/code>.\nThis is where a conditional expression comes in:<\/p>\n<pre><code class=\"language-py\">steps = []\nfor n in range(100):\n    # Compute next value depending on n % 2\n    step = 3 * n + 1 if n % 2 else n \/\/ 2\n    steps.append(step)<\/code><\/pre>\n<p>At this point, the classic list comprehension pattern arises and you can rewrite the loop above as a list comprehension.\nTo give you a hand, I did it for you below.\nWhen using a conditional expression, I like to have the conditional expression by itself:<\/p>\n<pre><code class=\"language-py\">steps = [\n    3 * n + 1 if n % 2 else n \/\/ 2  # How to modify n\n    for n in range(100)             # Where to get n from\n]<\/code><\/pre>\n<p>To conclude, beware of a source of confusion:<\/p>\n<ul>\n<li>conditional expressions in the beginning; vs<\/li>\n<li>using <code>if<\/code> after a <code>for<\/code> to filter values.<\/li>\n<\/ul>\n<p>They do different things, and<\/p>\n<ul>\n<li>the former always looks like <code>... if ... else ...<\/code>; while<\/li>\n<li>the latter <em>cannot<\/em> have an <code>else<\/code>.<\/li>\n<\/ul>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1542633129999056897\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"In this short article I describe how to use conditional expressions in list comprehensions.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"Nested list comprehensions","date_published":"2022-06-20T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/nested-list-comprehensions","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/nested-list-comprehensions","content_html":"<p>In this short article I show you how to create nested list comprehensions.<\/p>\n\n<p>Did you know that <a href=\"\/blog\/pydonts\/list-comprehensions-101\">list comprehensions<\/a> can be nested?\nIt's not as bad as it sounds, I'll show you.<\/p>\n<p>List comprehensions are expressions: it's code that evaluates to a result.\nAnd list comprehensions can contain arbitrary expressions on the left...\nSo, list comprehensions can be nested!<\/p>\n<p>To nest list comprehensions, focus on one list comprehension at a time!\nHere is an example:<\/p>\n<pre><code class=\"language-py\"># Want to produce this pattern:\n# [[0, 1, 4], [9, 16, 25], [36, 49, 64]]\n\n# Double loop:\nresult = []\nfor i in range(3):\n    inner = []                          # Convert the\n    for j in range(3):                  # inner loop\n        inner.append((3 * i + j) ** 2)  # first.\n    result.append(inner)<\/code><\/pre>\n<p>To convert the double loop into a list comprehension, we start by focusing solely on the inner loop:<\/p>\n<pre><code class=\"language-py\"># Outer loop, inner list comprehension:\nresult = []\nfor i in range(3):\n    inner = [(3 * i + j) ** 2 for j in range(3)]\n    result.append(inner)\n\n# Without intermediate `inner` variable:\nresult = []\nfor i in range(3):\n    result.append([(3 * i + j) ** 2 for j in range(3)])\n#                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<\/code><\/pre>\n<p>Now that we converted the inner loop, we have the core loop pattern that hints at a list comprehension:<\/p>\n<ol>\n<li>initialisation of an empty list;<\/li>\n<li>a <code>for<\/code> loop; and<\/li>\n<li>appending to the same list over and over again.<\/li>\n<\/ol>\n<p>Thus, this can be converted to a list comprehension,\nas long as whatever is inside the call to <code>.append<\/code> goes in the beginning of the final list comprehension.<\/p>\n<pre><code class=\"language-py\"># Whatever was inside the `.append` goes in the beginning.\nresult = [[(3 * i + j) ** 2 for j in range(3)] for i in range(3)]\n#         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<\/code><\/pre>\n<p>Nested list comprehensions are at the frontier of what are acceptable list comprehensions.\nThey are great when all the list comprehensions involved are short and straightforward.<\/p>\n<p>By the way, when nesting list comprehensions, you may want to split them across multiple lines:<\/p>\n<pre><code class=\"language-py\"># This list comp...\nresult = [[(3 * i + j) ** 2 for j in range(3)] for i in range(3)]\n\n# ... is the same as this one:\nresult = [\n    [(3 * i + j) ** 2 for j in range(3)]\n    for i in range(3)\n]<\/code><\/pre>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1539018549989187584\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"In this short article I show you how to create nested list comprehensions.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]},{"title":"List comprehensions in functional programming","date_published":"2022-06-18T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/twitter-threads\/list-comprehensions-in-functional-programming","url":"https:\/\/mathspp.com\/blog\/twitter-threads\/list-comprehensions-in-functional-programming","content_html":"<p>In this short article I explain the relationship between list comprehensions and functional programming.<\/p>\n\n<p>Did you know that <a href=\"\/blog\/pydonts\/list-comprehensions-101\">list comprehensions<\/a> are actually a great tool for functional programming?<\/p>\n<p>The first thing that you need to understand is what the core of functional programming is.\nAnd while a bad CS class might make you think functional programming is all about <code>map<\/code> and <code>filter<\/code> and things like that...\nThat's not what FP is about!\nFP is about purity...<\/p>\n<p>Purity of what?\nPurity of results and behaviour.\nIn functional programming you are not supposed to produce side-effects.<\/p>\n<p>Proper discussion of this would make for a huge article, so let's stick with this:<\/p>\n<blockquote>\n<p>In functional programming, we (typically) don't want side-effects.<\/p>\n<\/blockquote>\n<p>List comprehensions provide just that:\nList comprehensions provide a way to transform iterables into new lists without having a single side-effect!<\/p>\n<p>This is not true for the equivalent <code>for<\/code>-loop.\nCheck the two examples below.\nThe <code>for<\/code> loop produces a variable as a side-effect:<\/p>\n<pre><code class=\"language-py\">squares = []\nfor num in range(10):\n    squares.append(num ** 2)\n\n# The loop is over and `num` still exists:\nprint(num)<\/code><\/pre>\n<p>But the list comprehension doesn't:<\/p>\n<pre><code class=\"language-py\">squares = [num ** 2 for num in range(10)]\n\n# The list comp is over and `num` does NOT exist:\nprint(num)  # NameError: 'num' is not defined.<\/code><\/pre>\n<p>So, list comprehensions produce no side-effects by themselves...\nAnd that's also why you are typically advised against doing work in list comprehensions that produces side-effects.<\/p>\n<p>For example, many people have sent me list comprehension solutions that look something like this:<\/p>\n<pre><code class=\"language-py\">squares = []\n[squares.append(num ** 2) for num in range(10)]<\/code><\/pre>\n<p>What's the issue here?\nThe issue is that the list comprehension is producing side-effects:\nAs a side-effect to the list comprehension running, the list called <code>squares<\/code> is growing!<\/p>\n<p>That's a big no no!<\/p>\n<p>On top of that, you are defeating the purpose of list comprehensions...\nBecause you used a list comprehension to build a list that you just ignored!\nSo, for now, remember: <strong>list comprehensions should produce no side-effects<\/strong>.<\/p>\n<p>And let us end with a quiz:\nWhat's the output of the code below?\nThat should help clarify why it doesn't make much sense to use <code>.append<\/code> inside a list comprehension.<\/p>\n<pre><code class=\"language-py\">squares = []\nlist_comp = [squares.append(num ** 2) for num in range(10)]\nprint(list_comp)<\/code><\/pre>\n<div class=\"notices green\">\n<p>This article was generated automatically from <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1538206477726404609\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this thread<\/a> I published on Twitter <a href=\"https:\/\/twitter.com\/mathsppblog\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@mathsppblog<\/a>.\nThen it was edited lightly.<\/p>\n<\/div>","summary":"In this short article I explain the relationship between list comprehensions and functional programming.","date_modified":"2024-08-10T20:53:03+02:00","tags":["programming","python"]}]}
