{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/pt\/blog","feed_url":"https:\/\/mathspp.com\/pt\/blog.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":"TIL #012 \u2013 At operator for matrix multiplication","date_published":"2021-10-12T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/012","url":"https:\/\/mathspp.com\/pt\/blog\/til\/012","content_html":"

Today I learned that Python 3.5+ supports the operator @<\/code> for matrix multiplication.<\/p>\n\n<\/script>\n<p><img alt=\"Snippet of Python code using @ with numpy.\" src=\"\/images\/5\/3\/3\/9\/e\/5339eeaa680a36e342f0abad6d043fb33a04e1d9-thumbnail.png\"><\/p>\n<h1>At operator <code>@<\/code>\n<\/h1>\n<p><a href=\"https:\/\/docs.python.org\/3\/whatsnew\/3.5.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Since Python 3.5<\/a>, Python has the infix operator <code>@<\/code>.\nThis operator was introduced with <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0465\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">PEP 465<\/a> to be used in matrix multiplication.<\/p>\n<p>You can try to use it with just vanilla Python,\nbut no vanilla Python types define their behaviour with <code>@<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; 3 @ 5\nTraceback (most recent call last):\n File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\nTypeError: unsupported operand type(s) for @: 'int' and 'int'<\/code><\/pre>\n<p>However, just looking at the error above, you see that the error is in <code>@<\/code>\nnot knowing what to do with integers.\nThe error <em>is not<\/em> the fact that <code>@<\/code> is an invalid operator!\nSo cool!<\/p>\n<h1>Matrix multiplication in <code>numpy<\/code> with <code>@<\/code>\n<\/h1>\n<p>If you have <code>numpy<\/code> at hand, you can check <code>@<\/code> works,\nbecause <code>numpy<\/code> arrays added support to be used with <code>@<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; import numpy as np\n&gt;&gt;&gt; np.random.rand(3, 3) @ np.random.rand(3, 3)\narray([[0.89431673, 0.57949659, 0.59470797],\n [0.47364302, 0.29837518, 0.33552972],\n [1.12634752, 0.75218169, 0.78876082]])\n&gt;&gt;&gt; _ @ np.eye(3) # The identity (eye) matrix leaves the other matrix unchanged.\narray([[0.89431673, 0.57949659, 0.59470797],\n [0.47364302, 0.29837518, 0.33552972],\n [1.12634752, 0.75218169, 0.78876082]])<\/code><\/pre>\n<div class=\"notices yellow\">\n<p><code>_<\/code> is just a way to refer to the last result of the REPL.\nRead about it in <a href=\"https:\/\/mathspp.com\/blog\/pydonts\/usages-of-underscore#recovering-last-result-in-the-session\">this Pydon't<\/a>.<\/p>\n<\/div>\n<h1>Using <code>@<\/code> with custom classes\/types<\/h1>\n<p>If you want your own objects to add support for <code>@<\/code>,\nall you have to do is implement the dunder methods <code>__matmul__<\/code> and <code>__rmatmul__<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; class Dummy:\n... def __matmul__(self, other):\n... print(\"Works!\")\n... return 42\n... def __rmatmul__(self, other):\n... print(\"Also works!\")\n... return 73\n...\n&gt;&gt;&gt; d = Dummy()\n&gt;&gt;&gt; d @ 1\nWorks!\n42\n&gt;&gt;&gt; 1 @ d\nAlso works!\n73<\/code><\/pre>\n<p>There's also the <code>__imatmul__<\/code> method for in-place matrix multiplication:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; class Dummy:\n... def __imatmul__(self, other):\n... print(\"In-place!\")\n...\n&gt;&gt;&gt; d = Dummy()\n&gt;&gt;&gt; d @= 1\nIn-place!<\/code><\/pre>\n<p>Of course, this silly example above doesn't show you the proper semantics of the <code>__matmul__<\/code>,\n<code>__rmatmul__<\/code>, and <code>__imatmul__<\/code> methods.\nIt just shows you they exist and they interact with the operator <code>@<\/code>!<\/p>\n<p>By the way, for reference, here is the tweet that showed me this:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p lang=\"en\" dir=\"ltr\">How did I not know @ was a proper operator?!<\/p>\u2014 Rodrigo \ud83d\udc0d\ud83d\udcdd (@mathsppblog) <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1447905365316734982?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">October 12, 2021<\/a>\n<\/blockquote>\n<p>That's it for now! <a href=\"\/pt\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned that Python 3.5+ supports the operator @ for matrix multiplication.","date_modified":"2021-10-12T15:00:09+02:00","tags":["mathematics","numpy","programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/012-at-operator-for-matrix-multiplication\/thumbnail.png"},{"title":"TIL #011 \u2013 emojis in Python with pythonji","date_published":"2021-10-11T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/011","url":"https:\/\/mathspp.com\/pt\/blog\/til\/011","content_html":"<p>Today I learned that you can use emojis as variable names in Python if you use <code>pythonji<\/code>.<\/p>\n\n<p><img alt=\"Snippet of Python code written with emojis.\" src=\"\/images\/f\/8\/3\/9\/8\/f8398faf1913d46e756bdd4fed6530475616f102-thumbnail.png\"><\/p>\n<h1>Can you use emojis in Python?<\/h1>\n<p>No!\nAt the time of writing, emojis are not valid Python identifiers.\nThis means that this code fails:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; \ud83c\udf54 = \"hamburguer\" # SyntaxError<\/code><\/pre>\n<p>However, if you install the package <a href=\"https:\/\/github.com\/gahjelle\/pythonji\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">\n <code>pythonji<\/code>\n<\/a>,\nyou will be able to run code like that!<\/p>\n<p>Installing <code>pythonji<\/code> is as easy as <code>python -m pip install pythonji<\/code>!<\/p>\n<p>With <code>pythonji<\/code> installed, we can run programs that make use of emojis!<\/p>\n<p>Here's a little program I wrote:<\/p>\n<pre><code class=\"language-py\">import enum\n\nclass \ud83c\udf7d(enum.Enum):\n \ud83c\udf54 = \"hamburguer\"\n \ud83c\udf55 = \"pizza\"\n \ud83c\udf45 = \"tomato\"\n \ud83e\udd55 = \"carrot\"\n\nclass \ud83e\uddcd:\n def __init__(\ud83e\udd33, \ud83d\ude0b\ud83d\udc4d):\n \ud83e\udd33.\ud83d\ude0b\ud83d\udc4d = \ud83d\ude0b\ud83d\udc4d\n\n def \ud83c\udf7d(\ud83e\udd33, \ud83d\ude0b):\n if \ud83d\ude0b in \ud83e\udd33.\ud83d\ude0b\ud83d\udc4d:\n return \"Yummi!\"\n else:\n return \"Ok, I'll eat that.\"\n\n\ud83d\udc68 = \ud83e\uddcd([\ud83c\udf7d.\ud83c\udf55, \ud83c\udf7d.\ud83e\udd55])\nprint(\ud83d\udc68.\ud83c\udf7d(\ud83c\udf7d.\ud83c\udf55))\nprint(\ud83d\udc68.\ud83c\udf7d(\ud83c\udf7d.\ud83c\udf45))<\/code><\/pre>\n<p>Save it to the file <code>foo.\ud83d\udc0d<\/code> (yes, the extension really is \ud83d\udc0d!).<\/p>\n<p>Now, run it with <code>pythonji foo.\ud83d\udc0d<\/code> and this is the output:<\/p>\n<pre><code class=\"language-bash\"> &gt; pythonji foo.\ud83d\udc0d\nYummi!\nOk, I'll eat that.<\/code><\/pre>\n<p>Amazing, right? \ud83d\ude06<\/p>\n<p>That's it for now! <a href=\"\/pt\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned that you can use emojis as variable names in Python if you use pythonji.","date_modified":"2021-10-12T15:00:09+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/011-emojis-in-python-with-pythonji\/thumbnail.png"},{"title":"TIL #010 \u2013 generator return","date_published":"2021-10-09T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/010","url":"https:\/\/mathspp.com\/pt\/blog\/til\/010","content_html":"<p>Today I learned that Python generators can return a value.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<p><img alt=\"Code showing a generator that returns a value.\" src=\"\/images\/3\/c\/0\/f\/9\/3c0f99b787d5af15f5c5557fbaaaff9c38d847f1-thumbnail.png\"><\/p>\n<h1>Generators<\/h1>\n<p>Generators are interesting Python objects that produce a series of values,\nbut one by one.\nIn a way, they can be thought of as stateful functions.\n(That is, functions with state.)<\/p>\n<p>What I learned is that generators can also return something.\nHere is the tweet that prompted this discovery:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p lang=\"en\" dir=\"ltr\"><a href=\"https:\/\/twitter.com\/hashtag\/Python?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">#Python<\/a> pop quiz: Is this code valid? If so, what does it do?<br><br>def f():<br> yield 10<br> return 20<br><br>g = f()<br>print(next(g))<br>print(next(g))<\/p>\u2014 Raymond Hettinger (@raymondh) <a href=\"https:\/\/twitter.com\/raymondh\/status\/1446191250470735878?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">October 7, 2021<\/a>\n<\/blockquote>\n<h1>Returning from a generator<\/h1>\n<p>When you use a <code>return<\/code> inside a generator,\nthe generator will have that returned information in its <code>StopIteration<\/code>\nexception when it's done:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; def f():\n... yield 10\n... return 20\n...\n&gt;&gt;&gt; gen = f()\n&gt;&gt;&gt; next(gen)\n10\n&gt;&gt;&gt; next(gen)\nTraceback (most recent call last):\n File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\nStopIteration: 20<\/code><\/pre>\n<p>If you want to get access to that value, you just need to catch the exception:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; gen = f(); next(gen);\n10\n&gt;&gt;&gt; try:\n... next(gen)\n... except StopIteration as e:\n... val = e.value\n...\n&gt;&gt;&gt; val\n20<\/code><\/pre>\n<p>That's it for now! <a href=\"\/pt\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned that Python generators can return a value.","date_modified":"2021-10-10T01:56:57+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/010-generator-return\/thumbnail.png"},{"title":"TIL #009 \u2013 vars","date_published":"2021-10-07T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/009","url":"https:\/\/mathspp.com\/pt\/blog\/til\/009","content_html":"<p>Today I learned about the built-in function <code>vars<\/code> in Python.<\/p>\n\n<p><img alt=\"Example usage of vars in the Python REPL.\" src=\"\/images\/d\/4\/a\/c\/b\/d4acb3bf113ea6894eb9b8770f2887faa31736a0-thumbnail.png\"><\/p>\n<h1><code>vars<\/code><\/h1>\n<p>Python has a bunch of built-in functions.\nLike, a lot!\nIt's very difficult to keep track of all of them, remember them,\nand use them correctly.<\/p>\n<p>A built-in function I just learned about is <code>vars<\/code>.\nI heard about it from Reuven Lerner (a Python trainer) in <a href=\"https:\/\/sparklp.co\/4958f81b\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">his newsletter \u201cBetter Developers\u201d<\/a>.\n(Disclaimer: that's a referral link, but I <em>am<\/em> a subscriber and avid reader of the newsletter,\nso it is a very honest recommendation!)<\/p>\n<p>Looking at the <a href=\"https:\/\/docs.python.org\/3\/library\/functions.html#vars\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Python documentation<\/a>, we can see what <code>vars<\/code> does:<\/p>\n<blockquote>\n<p>\u201cReturn the <code>__dict__<\/code> attribute for a module, class, instance, or any other object with a <code>__dict__<\/code> attribute.\u201d<\/p>\n<\/blockquote>\n<p>The documentation also goes on to say that \u201cwithout an argument, <code>vars()<\/code> acts like <code>locals()<\/code>.\u201d.\nSo that's not useful because we can always use <code>locals()<\/code>.<\/p>\n<p>When <code>vars<\/code> really shines is when you give it an argument, like a module or a class instance!<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; class Person:\n... def __init__(self, name):\n... self.name = name\n...\n&gt;&gt;&gt; p = Person(\"me\")\n&gt;&gt;&gt; vars(p)\n{'name': 'me'}<\/code><\/pre>\n<p>So, we can see that <code>vars<\/code> is a very handy way of inspecting an instance of a class you defined.\nQuite cool, right?<\/p>\n<p>For things like built-in classes, or modules, <code>vars<\/code> is similar to <code>dir<\/code>.\nRecall that <code>dir<\/code> lists the names of all the attributes of an object,\nbut <code>vars<\/code> will give you a mapping with the names of the attributes and the corresponding values:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; import math\n&gt;&gt;&gt; dir(math)\n['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp']\n&gt;&gt;&gt; vars(math)\n{'__name__': 'math', '__doc__': 'This module provides access to the mathematical functions\\ndefined by the C standard.', ...}<\/code><\/pre>\n<p>That's it for now! <a href=\"\/pt\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned about the built-in function vars in Python.","date_modified":"2021-10-07T23:30:33+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/009-vars\/thumbnail.png"},{"title":"Problema #046 \u2013 grelha com tri\u00e2ngulos","date_published":"2021-10-03T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/problems\/triangle-grid","url":"https:\/\/mathspp.com\/pt\/blog\/problems\/triangle-grid","content_html":"<p>Consegues desenhar 4 tri\u00e2ngulos nesta grelha 5 por 5 e cobrir todos os pontos?<\/p>\n\n<p><img alt=\"\" src=\"\/images\/1\/d\/d\/f\/8\/1ddf818678c62704adbf44860837ce12258467d7-thumbnail.png\"><\/p>\n<h1>Enunciado do problema<\/h1>\n<p>O teu objetivo \u00e9 desenhar 4 tri\u00e2ngulos numa grelha 5 por 5.\nClaro que h\u00e1 algumas restri\u00e7\u00f5es:<\/p>\n<ul>\n<li>todos os v\u00e9rtices de todos os tri\u00e2ngulos t\u00eam de estar sobre pontos da grelha;<\/li>\n<li>os 25 pontos da grelha t\u00eam de ser atravessados por uma aresta de algum tri\u00e2ngulo,\nou estar sob algum v\u00e9rtice; e<\/li>\n<li>os tri\u00e2ngulos n\u00e3o podem ter \u00e2ngulos de 90\u2070 (por este motivo, conclu\u00edmos que a imagem em cima n\u00e3o \u00e9 parte da solu\u00e7\u00e3o, j\u00e1 que o tri\u00e2ngulo da direita tem um \u00e2ngulo de 90\u2070).<\/li>\n<\/ul>\n<div class=\"notices blue\">\n<p>Pensa um pouco!<\/p>\n<\/div>\n<p>Se precisares de clarificar alguma coisa, n\u00e3o hesites em perguntar na sec\u00e7\u00e3o de coment\u00e1rios em baixo.<\/p>\n<p>Eu encontrei este problema no site [Puzzling][source] da fam\u00edlia\nde sites do Stack Exchange.<\/p>\n<h1>Submiss\u00f5es<\/h1>\n<p>Parab\u00e9ns a todos os que conseguiram resolver o problema e,\nem particular, aos que me enviaram as suas solu\u00e7\u00f5es:<\/p>\n<ul>\n<li>David H., Taiwan;<\/li>\n<li>Michael W., Estados Unidos;<\/li>\n<li>Pedro G., Portugal;<\/li>\n<li>B. Praveen R., \u00cdndia;<\/li>\n<li>Kees L., Pa\u00edses Baixos;<\/li>\n<li>Jerry J., Estados Unidos;<\/li>\n<li>Mihalis G., Gr\u00e9cia;<\/li>\n<li>Alfredo E., M\u00e9xico;<\/li>\n<\/ul>\n<p>Junta-te \u00e0 comunidade e envia-me a tua solu\u00e7\u00e3o por <a href=\"mailto:rodrigo@mathspp.com?subject=Resposta%20para%20Problema%20#046%20%E2%80%93%20grelha%20com%20tri%C3%A2ngulos\" class=\"mailto\">email<\/a>!<\/p>\n<h1>Solu\u00e7\u00e3o<\/h1>\n<p>Uma proposta de solu\u00e7\u00e3o vai ser publicada aqui quando tiverem passado duas semanas desde a publica\u00e7\u00e3o deste problema.<\/p>\n<p>N\u00e3o te esque\u00e7as de <a href=\"\/pt\/subscribe\">subscrever a newsletter<\/a> para receberes os problemas diretamente na tua caixa de correio.<\/p>","summary":"Consegues desenhar 4 tri\u00e2ngulos nesta grelha 5 por 5 e cobrir todos os pontos?","date_modified":"2021-10-09T16:43:22+02:00","tags":["geometry","mathematics"],"image":"\/user\/pages\/02.blog\/02.problems\/p046-triangle-grid\/thumbnail.png"},{"title":"TIL #008 \u2013 two pass join","date_published":"2021-09-30T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/008","url":"https:\/\/mathspp.com\/pt\/blog\/til\/008","content_html":"<p>Today I learned that the <code>.join<\/code> method in Python is a two-pass algorithm, and that's why joining a list comprehension is faster than a generator expression.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><p><img alt=\"Code showing that joining list comprehensions is faster than joining generator expressions.\" src=\"\/images\/e\/2\/9\/8\/c\/e298c77b553d9763a942ce3746650cec6dc5d556-thumbnail.png\"><\/p>\n<h1>Context<\/h1>\n<p>My talk at EuroPython 2021 was finally <a href=\"https:\/\/www.youtube.com\/watch?v=Vjq89-spPOk\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">uploaded to YouTube<\/a>.\nI got really excited about this, so I decided to share it on Twitter:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p lang=\"en\" dir=\"ltr\">&#128680;&#128226; The recording &#128253; of my <a href=\"https:\/\/twitter.com\/europython?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@EuroPython<\/a> 2021 talk has been uploaded to YouTube!<br><br>In it, I walk you through the refactoring of a function, introducing many Python features.<br><br>Go watch it, and let me know if you find the Easter egg! &#129370; No one has, yet!<a href=\"https:\/\/t.co\/L3acpxN3mI\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">https:\/\/t.co\/L3acpxN3mI<\/a><\/p>&mdash; Rodrigo &#128013;&#128221; (@mathsppblog) <a href=\"https:\/\/twitter.com\/mathsppblog\/status\/1443184281098997764?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">September 29, 2021<\/a>\n<\/blockquote>\n<p>In my talk, I walk you through successive refactors of a piece of &ldquo;bad&rdquo; Python code,\nuntil you reach a &ldquo;better&rdquo; piece of Python code.\nThe talk follows closely the <a href=\"\/pt\/blog\/pydonts\/bite-sized-refactoring\">&ldquo;bite-sized refactoring&rdquo; Pydont'<\/a>.<\/p>\n<p>In the talk, I started with this code:<\/p>\n<pre><code class=\"language-py\">def myfunc(a):\n empty=[]\n for i in range(len(a)):\n if i%2==0:\n empty.append(a[i].upper())\n else:\n empty.append(a[i].lower())\n\n return \"\".join(empty)\n\n# ---\n&gt;&gt;&gt; myfunc(\"Hello, world!\")\n'HeLlO, wOrLd!'\n&gt;&gt;&gt; myfunc(\"Spongebob.\")\n'SpOnGeBoB.'<\/code><\/pre>\n<p>And refactored it up until this point:<\/p>\n<pre><code class=\"language-py\">def alternate_casing(text):\n return \"\".join([\n char.lower() if idx % 2 else char.upper()\n for idx, char in enumerate(text)\n ])<\/code><\/pre>\n<h1><code>.join<\/code><\/h1>\n<p>In a feedback tweet, someone said that I could've removed the <code>[]<\/code> of the list comprehension.\nThat would, instead, define a generator expression,\nthat should even be faster.<\/p>\n<p><em>Thankfully<\/em>, I was prepared for that:\nbefore the talk, I checked the performance of both alternatives,\nand found out that the generator expression was <em>not<\/em> faster.<\/p>\n<p>That surprised me, because I was under the impression that generator expressions\ntend to be faster that list comprehensions, but the data in front of me didn't lie...\nAnd so, I didn't change the list comprehension into a generator expression in the talk...<\/p>\n<p>But why is the generator expression slower?<\/p>\n<p>As it turns out, the <code>.join<\/code> method is a two-pass algorithm!<\/p>\n<p>At least, according to a tweet that was quoted to me:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p lang=\"en\" dir=\"ltr\">This is incorrect &mdash; due to the implementation of str.join, the list comprehension is faster (annoyingly) <a href=\"https:\/\/t.co\/gOdJm9hrd0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">https:\/\/t.co\/gOdJm9hrd0<\/a><\/p>&mdash; Alex Waygood (@AlexWaygood) <a href=\"https:\/\/twitter.com\/AlexWaygood\/status\/1443327768327041027?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">September 29, 2021<\/a>\n<\/blockquote>\n<p>Sadly, I haven't been able to verify this yet.<\/p>\n<p>However, it does make some sense:\nif <code>.join<\/code> really is a two-pass algorithm, then generator expressions hurt us,\nbecause generators can only be traversed once.\nTherefore, we need to do something before <code>.join<\/code> can actually start its work.<\/p>\n<p>Peeking at the source code for <code>.join<\/code> will probably reveal this...<\/p>\n<p>I'm a bit sleepy, but I'll interrupt typing <em>right now<\/em> to take a quick peek at the source,\nsee if I can find this code.<\/p>\n<p>[Me browsing through Python's source code.]<\/p>\n<p>Ok, I think I found it &#127881;&#127881;!<\/p>\n<p>In <a href=\"https:\/\/github.com\/python\/cpython\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Python's GitHub repo<\/a>, there's an <code>Objects<\/code> folder that contains a <code>stringlib<\/code>\nthat has a <code>join.h<\/code> file.\nOpening it, you can see that there are two <code>for<\/code> loops over the data.<\/p>\n<p>In the <a href=\"https:\/\/github.com\/python\/cpython\/tree\/d441437ee71ae174c008c23308b749b91020ba77\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">exact commit I looked at<\/a>, at the beginning of the 30th of September of 2021,\nthose two <code>for<\/code> loops start...<\/p>","summary":"Today I learned that the .join method in Python is a two-pass algorithm, and that&#039;s why joining a list comprehension is faster than a generator expression.","date_modified":"2021-10-07T23:30:33+02:00","tags":["algorithms","programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/008-two-pass-join\/thumbnail.png"},{"title":"TIL #007 \u2013 math.nextafter","date_published":"2021-09-29T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/007","url":"https:\/\/mathspp.com\/pt\/blog\/til\/007","content_html":"<p>Today I learned about the <code>math.nextafter<\/code> method.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><p><img alt=\"Code snippet showing the nextafter method.\" src=\"\/images\/4\/8\/7\/2\/c\/4872c65acdb86a75811e1195384e2cd7b78e4c91-thumbnail.png\"><\/p>\n<h1><code>math.nextafter<\/code><\/h1>\n<p>0 is a neat number, isn't it?<\/p>\n<p>Perhaps one of the greatest discoveries of mankind.<\/p>\n<p>But what's the number that comes after 0?\nThat would be the smallest number in the set <span class=\"mathjax mathjax--inline\">\$$]0, +\\inf[\$$<\/span>,\nif you're familiar with the mathematical notation for sets.<\/p>\n<p>In short, <span class=\"mathjax mathjax--inline\">\$$[a, b]\$$<\/span> is the contiguous set of numbers <span class=\"mathjax mathjax--inline\">\$$x\$$<\/span> that satisfy\nthe restriction <span class=\"mathjax mathjax--inline\">\$$a \\leq x \\leq b\$$<\/span>.\nNotice how <span class=\"mathjax mathjax--inline\">\$$a\$$<\/span> and <span class=\"mathjax mathjax--inline\">\$$b\$$<\/span> are included inside <span class=\"mathjax mathjax--inline\">\$$[a, b]\$$<\/span> because the brackets\nare closed.\nIf the brackets are open, then that number is not included.<\/p>\n<p>For the intervals below, <span class=\"mathjax mathjax--inline\">\$$x\$$<\/span> belongs to it if...<\/p>\n<ul><li><span class=\"mathjax mathjax--inline\">\$$[a, b]\$$<\/span> &rarr; <span class=\"mathjax mathjax--inline\">\$$a \\leq x \\leq b\$$<\/span>;<\/li>\n<li><span class=\"mathjax mathjax--inline\">\$$[a, b[\$$<\/span> &rarr; <span class=\"mathjax mathjax--inline\">\$$a \\leq x &lt; b\$$<\/span>;<\/li>\n<li><span class=\"mathjax mathjax--inline\">\$$]a, b]\$$<\/span> &rarr; <span class=\"mathjax mathjax--inline\">\$$a &lt; x \\leq b\$$<\/span>; and<\/li>\n<li><span class=\"mathjax mathjax--inline\">\$$]a, b[\$$<\/span> &rarr; <span class=\"mathjax mathjax--inline\">\$$a &lt; x &lt; b\$$<\/span>.<\/li>\n<\/ul><p>So, in <span class=\"mathjax mathjax--inline\">\$$]0, +\\infty[\$$<\/span>, nor 0, nor <span class=\"mathjax mathjax--inline\">\$$+\\infty\$$<\/span> are included.\nThus, what's the minimum element of this interval?\nWell, there isn't any!<\/p>\n<p>Mathematically speaking, there is no minimum in the interval <span class=\"mathjax mathjax--inline\">\$$]0, +\\infty[\$$<\/span>.\nWhy not?\nWhatever you pick as a potential minimum <span class=\"mathjax mathjax--inline\">\$$m\$$<\/span>, <span class=\"mathjax mathjax--inline\">\$$m\/2\$$<\/span> will be smaller than <span class=\"mathjax mathjax--inline\">\$$m\$$<\/span>\nand still be greater than <span class=\"mathjax mathjax--inline\">\$$0\$$<\/span>, that is, <span class=\"mathjax mathjax--inline\">\$$0 &lt; m\/2 &lt; m &lt; +\\infty\$$<\/span>,\nand so <span class=\"mathjax mathjax--inline\">\$$m\/2\$$<\/span> is in <span class=\"mathjax mathjax--inline\">\$$]0, +\\infty[\$$<\/span>.<\/p>\n<p>That's interesting, right?<\/p>\n<p>But this is a whole other story if we go into the programming real!\nBecause of how floats are represented,\nPython <em>has<\/em> a number that comes immediately after <code>0<\/code>.\nSo, what is it?<\/p>\n<p>Here it is:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; import math\n&gt;&gt;&gt; math.nextafter(0, 1)\n5e-324<\/code><\/pre>\n<p>That's <span class=\"mathjax mathjax--inline\">\$$5 \\times 10^{-324}\$$<\/span>, it's freakishly small!<\/p>\n<p>(Your result may differ from mine, although I'm not sure if it will.\nLeave a comment below if it does!)<\/p>\n<p>So, what's the role of the <code>math.nextafter<\/code> method?<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; help(math.nextafter)\nHelp on built-in function nextafter in module math:\n\nnextafter(x, y, \/)\n Return the next floating-point value after x towards y.<\/code><\/pre>\n<p>Hence, <code>nextafter<\/code> looks at <code>x<\/code> and then checks what's the float that's immediately next to <code>x<\/code>,\nif you walk in the direction of <code>y<\/code>.\nIf I set <code>x<\/code> to zero and <code>y<\/code> to one, I get the smallest float that Python can represent on my machine.<\/p>\n<p>So, what's the next float that Python can represent after <code>1<\/code>?<\/p>\n<p>Give it some thought.<\/p>\n<p>Here it is:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; math.nextafter(1, 999)\n1.0000000000000002<\/code><\/pre>\n<p>I'll be honest, for a second I thought it should've been <code>1 + 5e-324<\/code>,\nbut it makes sense it wasn't that.\nFloating point numbers have limited precision, right?\nAnd one thing that's limited is the size of the mantissa:\nthe stuff that comes after the decimal point.<\/p>\n<p>Above, we can see that the mantissa has 16 digits,\nand that's the size of the mantissa in Python.<\/p>\n<p>So, what's the next number after <code>10<\/code>?<\/p>\n<p>Give it some thought.<\/p>\n<p>Here it is:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; math.nextafter(10, 999)\n10.000000000000002<\/code><\/pre>\n<p>If you count, now there's only 15 digits to the right of the decimal point...\nBut...<\/p>","summary":"Today I learned about the math.nextafter method.","date_modified":"2021-10-07T23:30:33+02:00","tags":["arithmetics","mathematics","programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/007-nextafter\/thumbnail.png"},{"title":"Express\u00f5es condicionais | Pydon&#039;t \ud83d\udc0d","date_published":"2021-09-28T00:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/pydonts\/conditional-expressions","url":"https:\/\/mathspp.com\/pt\/blog\/pydonts\/conditional-expressions","content_html":"<p>Este Pydon't mostra-te como usar as express\u00f5es condicionais de Python, a alternativa ao operador tern\u00e1rio em Python.<\/p>\n\n<p><img alt=\"\" src=\"\/images\/c\/e\/e\/8\/e\/cee8e4e34ffe4bd4dabfe428411abb69a5064cb8-thumbnail.png\"><\/p>\n<p>(Se \u00e9s novo aqui e n\u00e3o sabes o que \u00e9 uma Pydon't, ent\u00e3o talvez queiras come\u00e7ar por\nler a <a href=\"\/pt\/blog\/pydonts\/pydont-manifesto\">Proclama\u00e7\u00e3o das Pydon'ts<\/a>.)<\/p>\n<p>Infelizmente, para poupar algum tempo, ainda n\u00e3o traduzi este artigo para portugu\u00eas...\nHei de o fazer eventualmente...\nSe quiseres, deixa um coment\u00e1rio em baixo a pedir que eu traduza o artigo ASAP ou <a href=\"https:\/\/github.com\/mathspp\/mathspp\/blob\/master\/pages\/02.blog\/04.pydonts\/the-power-of-reduce\/item.pt.md\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">submete um PR<\/a> com a tua tradu\u00e7\u00e3o.<\/p>","summary":"Este Pydon&#039;t mostra-te como usar as express\u00f5es condicionais de Python, a alternativa ao operador tern\u00e1rio em Python.","date_modified":"2021-10-02T18:29:26+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/01.pydonts\/conditional-expressions\/thumbnail.png"},{"title":"TIL #006 \u2013 file unpacking","date_published":"2021-09-24T21:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/til\/006","url":"https:\/\/mathspp.com\/pt\/blog\/til\/006","content_html":"<p>Today I learned that files can <em>also<\/em> be unpacked in Python.<\/p>\n\n<script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<p><img alt=\"Code snippet showing how to unpack strings.\" src=\"\/images\/2\/d\/f\/8\/1\/2df8100978586509c80e4b42cd7c095f65f952de-thumbnail.png\"><\/p>\n<h1>File unpacking<\/h1>\n<p><a href=\"\/pt\/blog\/til\/005\">After learning that strings can be unpacked in Python<\/a>,\nI shared the short article on Twitter.<\/p>\n<p>As a reply, <a href=\"https:\/\/twitter.com\/dabeaz\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">@dabeaz<\/a> suggested I tried doing it with a file:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p lang=\"en\" dir=\"ltr\">Now, try it with a file...<br><br>header, *data = open(\"somedata.csv\")<\/p>\u2014 David Beazley (@dabeaz) <a href=\"https:\/\/twitter.com\/dabeaz\/status\/1441405123540893703?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">September 24, 2021<\/a>\n<\/blockquote>\n<p>After seeing how strings can be unpacked,\nunpacking a file didn't look so weird, but it was still a pleasant surprise!<\/p>\n<p>But it \u201cdoes make sense\u201d, after all you can iterate directly over a file,\nwhich essentially iterates over the lines of the file.<\/p>\n<p>Grab a CSV file <code>\"my_data.csv\"<\/code>, for example with this data:<\/p>\n<pre><code class=\"language-csv\">Name, Surnames\nJohn, Doe\nMary, Smith<\/code><\/pre>\n<p>Then, in your Python REPL, you can get this to work:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; header, *data = open(\"my_data.csv\")\n&gt;&gt;&gt; header\n'Name, Surnames\\n'\n&gt;&gt;&gt; data\n['John, Doe\\n', 'Mary, Smith\\n']<\/code><\/pre>\n<p>It is not as useful as using the [<code>csv<\/code>][csv] module to read the CSV\ndata in and process it, but it is still a nifty trick.<\/p>\n<p>Come to think of it, if there is a place when this will be useful,\nprobably won't be with CSV files...<\/p>\n<p>I'll let you know if I put this little trick to good use!<\/p>\n<p>That's it for now! <a href=\"\/pt\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned that files can _also_ be unpacked in Python.","date_modified":"2021-10-07T23:30:33+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/03.til\/006-file-unpacking\/thumbnail.png"},{"title":"List comprehensions 101 | Pydon&#039;t \ud83d\udc0d","date_published":"2021-09-24T19:00:00+02:00","id":"https:\/\/mathspp.com\/pt\/blog\/pydonts\/list-comprehensions-101","url":"https:\/\/mathspp.com\/pt\/blog\/pydonts\/list-comprehensions-101","content_html":"<p>Este Pydon't ensina-te a usar list comprehensions em Python.<\/p>\n\n<p><img alt=\"\" src=\"\/images\/7\/8\/9\/9\/2\/789924bd28c6a17560b98cb851ae9ddf075a1b07-thumbnail.png\"><\/p>\n<p>(Se \u00e9s novo aqui e n\u00e3o sabes o que \u00e9 uma Pydon't, ent\u00e3o talvez queiras come\u00e7ar por\nler a <a href=\"\/pt\/blog\/pydonts\/pydont-manifesto\">Proclama\u00e7\u00e3o das Pydon'ts<\/a>.)<\/p>\n<p>Infelizmente, para poupar algum tempo, ainda n\u00e3o traduzi este artigo para portugu\u00eas...\nHei de o fazer eventualmente...\nSe quiseres, deixa um coment\u00e1rio em baixo a pedir que eu traduza o artigo ASAP ou <a href=\"https:\/\/github.com\/mathspp\/mathspp\/blob\/master\/pages\/02.blog\/04.pydonts\/the-power-of-reduce\/item.pt.md\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">submete um PR<\/a> com a tua tradu\u00e7\u00e3o.<\/p>","summary":"Este Pydon&#039;t ensina-te a usar list comprehensions em Python.","date_modified":"2021-09-29T07:08:30+02:00","tags":["programming","python"],"image":"\/user\/pages\/02.blog\/01.pydonts\/list-comprehensions-101\/thumbnail.png"}]}