
    
        
        
        
                
        
        
        
                
        
        
        
            
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/tags\/typing","feed_url":"https:\/\/mathspp.com\/blog\/tags\/typing.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 #084 \u2013 type statement and type aliases","date_published":"2023-10-03T10:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/type-statement-and-type-aliases","url":"https:\/\/mathspp.com\/blog\/til\/type-statement-and-type-aliases","content_html":"<p>Today I learned about the Python 3.12 type statement you can use to create type aliases.<\/p>\n\n<h2 id=\"type-statement-and-type-aliases\"><code>type<\/code> statement and type aliases<a href=\"#type-statement-and-type-aliases\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Python 3.12 introduced the soft keyword <code>type<\/code>, which is used in the <code>type<\/code> statement to create type aliases.\nThe <code>type<\/code> statement offers a more convenient <a href=\"#forward-references\">and powerful<\/a> way of creating type aliases and it supersedes <code>typing.TypeAlias<\/code>.<\/p>\n<p>In its simplest form, the <code>type<\/code> statement is composed of the <code>type<\/code> keyword, the name of the type alias you are creating, and the type you are aliasing.\nThe example below shows how to create a type alias called <code>Point<\/code> that is the same as a pair with two floats:<\/p>\n<pre><code class=\"language-py\">type Point = tuple[float, float]<\/code><\/pre>\n<p>Before the introduction of the <code>type<\/code> statement, you could create a type alias via a regular assignment:<\/p>\n<pre><code class=\"language-py\">Point = tuple[float, float]<\/code><\/pre>\n<p>You could also annotate <code>Point<\/code> with <code>typing.TypeAlias<\/code> to make it clear that you were creating a type alias:<\/p>\n<pre><code class=\"language-py\">from typing import TypeAlias\n\nPoint: TypeAlias = tuple[float, float]<\/code><\/pre>\n<p>So, why do we care about the <code>type<\/code> statement?<\/p>\n<h3 id=\"forward-references\">Forward references<a href=\"#forward-references\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>One of the advantages of the <code>type<\/code> statement is that it supports forward referencing without having to quote the names of the types you are refering to.\nThis is possible because the type value is lazily evaluated.<\/p>\n<p>For example, suppose we want to create a recursive type for a linked list, where a linked list is a tuple with two elements: an integer and a linked list (the remainder of the linked list).\nIn 3.12, you could write it as such:<\/p>\n<pre><code class=\"language-py\">type LinkedList = tuple[int, LinkedList]<\/code><\/pre>\n<p>The self-reference works just fine, and so does the forward reference of the example below:<\/p>\n<pre><code class=\"language-py\">type A = tuple[B, C, D]\ntype B = int\ntype C = str\ntype D = list[str]<\/code><\/pre>\n<p>In Python 3.11 and earlier, you'd have to quote the forward references or the self-reference of the first example, like so:<\/p>\n<pre><code class=\"language-py\">from typing import TypeAlias\n\nLinkedList: TypeAlias = tuple[int, \"LinkedList\"]\n\nA: TypeAlias = tuple[\"A\", \"B\", \"C\"]\nB: TypeAlias = int\nC: TypeAlias = str\nD: TypeAlias = list[str]<\/code><\/pre>\n<h3 id=\"generic-type-aliases\">Generic type aliases<a href=\"#generic-type-aliases\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>Type aliases can also be made generic.\nFor example, the linked list could be a linked list of any kind of value we want, not just integers.<\/p>\n<p>We could type the linked list like so:<\/p>\n<pre><code class=\"language-py\">type LinkedList[T] = T | tuple[T, LinkedList[T]]<\/code><\/pre>\n<p>This means that a linked list is either a value of its type <code>T<\/code> or it is a pair with a value and a linked list.<\/p>\n<p>For example, the variable <code>ll<\/code> below defines a linked list of integers:<\/p>\n<pre><code class=\"language-py\">ll: LinkedList[int] = (42, (73, (10, (16, 0))))<\/code><\/pre>\n<p>This is just the tip of the iceberg.\nGenerics were also improved in Python 3.12, so there's even more you can do.\nYou can take a look at the <a href=\"#references\">references<\/a> below to learn more about this.<\/p>","summary":"Today I learned about the Python 3.12 type statement you can use to create type aliases.","date_modified":"2025-07-23T16:49:02+02:00","tags":["programming","python","typing"],"image":"\/user\/pages\/02.blog\/04.til\/084.type-statement-and-type-aliases\/thumbnail.webp"},{"title":"TIL #083 \u2013 sentinel value for default arguments","date_published":"2023-09-15T21:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/til\/sentinel-value-for-default-arguments","url":"https:\/\/mathspp.com\/blog\/til\/sentinel-value-for-default-arguments","content_html":"<p>Today I learned how to create a sentinel value to use as a default argument in a way that respects Python typing.<\/p>\n\n<h2 id=\"sentinel-value-for-default-arguments\">Sentinel value for default arguments<a href=\"#sentinel-value-for-default-arguments\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<h3 id=\"context\">Context<a href=\"#context\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>Today at work I had a problem.\nI was working on a progress bar that <a href=\"https:\/\/github.com\/textualize\/textual\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Textual<\/a> has:<\/p>\n<p><img alt=\"A screenshot of a thin progress bar inside a Textual application.\" src=\"\/user\/pages\/02.blog\/04.til\/083.sentinel-value-for-default-arguments\/_progress_bar.webp\"><\/p>\n<p>The <code>ProgressBar<\/code> class has a method <code>update<\/code> that you can use to update the status of the progress bar.\nThe method <code>update<\/code> looked <em>roughly<\/em> like this:<\/p>\n<pre><code class=\"language-py\">class ProgressBar(...):\n    ...\n\n    def update(\n        self,\n        total: float | None = None,\n        progress: float | None = None,\n        advance: float | None = None,\n    ) -&gt; None:\n        \"\"\"Update the status of the progress bar.\"\"\"\n        if total is not None:\n            self.total = total\n        if progress is not None:\n            self.progress = progress\n        if advance is not None:\n            self.progress += advance<\/code><\/pre>\n<p>By calling <code>update<\/code>, you can change the total &ldquo;size&rdquo; of the progress bar (<code>total<\/code>), you can change how far along you are with the progress (<code>progress<\/code>), and you can increment the current progress by a given amount (<code>advance<\/code>).<\/p>\n<p>For example, if you create a progress bar <code>pb<\/code> and then call <code>pb.update(total=100, progress=30, advance=7)<\/code>, your progress bar ends up at 37% completion and it would look something like this:<\/p>\n<p><img alt=\"A screenshot of a progress bar in a Textual application that is at 37%.\" src=\"\/user\/pages\/02.blog\/04.til\/083.sentinel-value-for-default-arguments\/_progress_bar_37.webp\"><\/p>\n<p>What's the problem, then?<\/p>\n<h3 id=\"using-another-default-value-instead-of-none\">Using another default value instead of <code>None<\/code>\n<a href=\"#using-another-default-value-instead-of-none\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>The default value for <code>total<\/code> is <code>None<\/code>, but the truth is that I also want to be able to set <code>total<\/code> to <code>None<\/code>, because that turns the progress bar into its indeterminate\/pulsing state.\nSo, how can I do this?<\/p>\n<p>The answer is obvious: just use another default value!<\/p>\n<p>That's right, but I can't use any random default value, because then the typing will look odd!\nFor example, I could use the string <code>\"default\"<\/code>, and modify the method to look like this:<\/p>\n<pre><code class=\"language-py\">class ProgressBar(...):\n    ...\n\n    def update(\n        self,\n        total: float | str | None = \"default\",\n        progress: float | None = None,\n        advance: float | None = None,\n    ) -&gt; None:\n        \"\"\"Update the status of the progress bar.\"\"\"\n        if not isinstance(total, str):\n            self.total = total\n        if progress is not None:\n            self.progress = progress\n        if advance is not None:\n            self.progress += advance<\/code><\/pre>\n<p>The problem with this, I argue, is that it looks really odd to have <code>total<\/code> accept values of the type <code>str<\/code>, when it really doesn't, it's just so that the typing matches the default value given...<\/p>\n<p>In other words, if I just had<\/p>\n<pre><code class=\"language-py\">...\ntotal: float | None = \"default\",\n...<\/code><\/pre>\n<p>then the typing would be wrong.\nAnd I want to have the code typed correctly, if possible.<\/p>\n<p>So, how do we solve this?<\/p>\n<h3 id=\"using-object-as-the-default-value\">Using <code>object<\/code> as the default value<a href=\"#using-object-as-the-default-value\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>My next thought went to using <code>object<\/code> as the default value.\nSo, something like this:<\/p>\n<pre><code class=\"language-py\">_sentinel = object()\n\nclass ProgressBar(...):\n    ...\n\n    def update(\n        self,\n        total: float | None | object = _sentinel,\n        progress: float | object = _sentinel,\n        advance: float | object = _sentinel,\n    ) -&gt; None:\n        \"\"\"Update the status of the progress bar.\"\"\"\n        if total is not _sentinel:\n            self.total...<\/code><\/pre>","summary":"Today I learned how to create a sentinel value to use as a default argument in a way that respects Python typing.","date_modified":"2025-07-23T16:49:02+02:00","tags":["programming","python","typing"],"image":"\/user\/pages\/02.blog\/04.til\/083.sentinel-value-for-default-arguments\/thumbnail.webp"},{"title":"TIL #054 \u2013 type hint Any","date_published":"2022-11-04T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/til\/type-hint-any","url":"https:\/\/mathspp.com\/blog\/til\/type-hint-any","content_html":"<p>Today I learned about the type hint <code>Any<\/code> and its bidirectional compatibility with all other types.<\/p>\n\n<h2 id=\"type-hint-any\">Type hint <code>Any<\/code><a href=\"#type-hint-any\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The special type <code>Any<\/code> provided in the module <code>typing<\/code> is a type that matches <em>all<\/em> Python objects.\nThe documentation says that <code>Any<\/code> is compatible with all other types and all other types are compatible with <code>Any<\/code>.<\/p>\n<p>I have a limited understanding of type hints in Python, but I don't think this sentence is redundant:<\/p>\n<blockquote>\n<p>&ldquo;A static type checker will treat every type as being compatible with <code>Any<\/code> and <code>Any<\/code> as being compatible with every type.&rdquo;<\/p>\n<\/blockquote>\n<p>This <em>compatibility<\/em> seems to be related to subclasses and the methods and attributes that objects provide.<\/p>\n<p>For example, suppose we have this class hierarchy:<\/p>\n<pre><code class=\"language-py\">class Animal:\n    pass\n\nclass Human(Animal):\n    pass<\/code><\/pre>\n<p>All instances of <code>Human<\/code> are also instances of <code>Animal<\/code> (because <code>Human<\/code> is a subclass of <code>Animal<\/code>) but there may be instances of <code>Animal<\/code> that are not instances of <code>Human<\/code>.\nFor example, dolphins are definitely animals and also definitely not humans.<\/p>\n<p>So, the type <code>Human<\/code> is compatible with the type <code>Animal<\/code>.\nWhy?\nBecause all instances of <code>Human<\/code> can also be seen as instances of <code>Animal<\/code>.\nIn fact, the function below would pass static type checking:<\/p>\n<pre><code class=\"language-py\">def foo(human: Human) -&gt; Animal:\n    return human<\/code><\/pre>\n<p>However, the reverse does <strong>not<\/strong> pass static type checking:<\/p>\n<pre><code class=\"language-py\">def bar(animal: Animal) -&gt; Human:\n    return animal<\/code><\/pre>\n<p>The static type checker complains with &ldquo;<code>Animal<\/code> is incompatible with <code>Human<\/code>&rdquo;.\nSo, if <code>Any<\/code> is compatible with all types and if all types are compatible with <code>Any<\/code>, this means the functions <code>f<\/code> and <code>g<\/code> below should pass static type checking:<\/p>\n<pre><code class=\"language-py\">from typing import Any\n\ndef f(x: int) -&gt; Any:\n    return x\n\ndef g(x: Any) -&gt; int:\n    return x<\/code><\/pre>\n<p>And they do.\nIf you run a static type checker against the functions <code>f<\/code> and <code>g<\/code>, they both pass static type checking.<\/p>\n<p>What bothers me is that the function <code>g<\/code> seems to be typed improperly.\nAfter all, I can write this code:<\/p>\n<pre><code class=\"language-py\">from typing import Any\n\ndef g(x: Any) -&gt; int:\n    return x\n\nprint(g(\"Hello, world!\"))<\/code><\/pre>\n<p>Running this code will print a string (and the function <code>g<\/code> has a type hint saying it returns an integer) but the code passes static type checking!\nAfter all, we have that:<\/p>\n<ul><li>the function <code>g<\/code> is correctly typed because the return value <code>x<\/code> is of type <code>Any<\/code>, and <code>Any<\/code> is compatible with <code>int<\/code>; and<\/li>\n<li>the function call <code>g(\"Hello, world!\")<\/code> is also ok because the argument is of type <code>str<\/code> and the function <code>g<\/code> expects an argument of type <code>Any<\/code>. The type <code>str<\/code> is compatible with <code>Any<\/code>, so this function call is ok.<\/li>\n<\/ul><h3 id=\"what-is-any-used-for\">What is <code>Any<\/code> used for?<a href=\"#what-is-any-used-for\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>So, why is <code>Any<\/code> useful if it gives you total freedom and doesn't seem to do anything for you?\n<code>Any<\/code> is useful for gradually adding types to an untyped codebase.\nSo, if you have some code that you'd like to typecheck, you can start by inserting <code>Any<\/code> everywhere, and the code will typecheck.\nThen, you can...<\/p>","summary":"Today I learned about the type hint `Any` and its bidirectional compatibility with all other types.","date_modified":"2025-07-23T16:49:02+02:00","tags":["programming","python","typing"],"image":"\/user\/pages\/02.blog\/04.til\/054.type-hint-Any\/thumbnail.webp"}]}
