<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Matteo</title>
    <description>The latest articles on Forem by Matteo (@matteospanio).</description>
    <link>https://forem.com/matteospanio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F738482%2F40db7e52-d4e0-40da-8b3c-5c7d80e0068f.jpg</url>
      <title>Forem: Matteo</title>
      <link>https://forem.com/matteospanio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/matteospanio"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Matteo</dc:creator>
      <pubDate>Fri, 29 Aug 2025 15:32:12 +0000</pubDate>
      <link>https://forem.com/matteospanio/-2fo0</link>
      <guid>https://forem.com/matteospanio/-2fo0</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46" class="crayons-story__hidden-navigation-link"&gt;Making scientific python blazingly fast with PyTorch&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/matteospanio" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F738482%2F40db7e52-d4e0-40da-8b3c-5c7d80e0068f.jpg" alt="matteospanio profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/matteospanio" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Matteo
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Matteo
                
              
              &lt;div id="story-author-preview-content-2806123" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/matteospanio" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F738482%2F40db7e52-d4e0-40da-8b3c-5c7d80e0068f.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Matteo&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 29 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46" id="article-link-2806123"&gt;
          Making scientific python blazingly fast with PyTorch
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gpu"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gpu&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/performance"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;performance&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>gpu</category>
      <category>python</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>Making scientific python blazingly fast with PyTorch</title>
      <dc:creator>Matteo</dc:creator>
      <pubDate>Fri, 29 Aug 2025 13:42:22 +0000</pubDate>
      <link>https://forem.com/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46</link>
      <guid>https://forem.com/matteospanio/making-scientific-python-blazingly-fast-with-pytorch-2h46</guid>
      <description>&lt;p&gt;If you’ve ever written scientific code in Python, you know the stack Numpy + Scipy, a lot of people say it is fast, but to me not fast enough. In my recent paper &lt;em&gt;&lt;a href="https://dafx25.dii.univpm.it/wp-content/uploads/2025/07/DAFx25_paper_65.pdf" rel="noopener noreferrer"&gt;TorchFX: A Modern Approach to Audio DSP with PyTorch and GPU Acceleration&lt;/a&gt;&lt;/em&gt; (DAFx25), I explored a solution to this long-standing problem.&lt;/p&gt;

&lt;p&gt;The idea is simple yet powerful: instead of relying on the traditional NumPy + SciPy stack, we can swap them out for PyTorch, instantly gaining GPU acceleration, an object-oriented API, and direct compatibility with AI workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  The slow python problem
&lt;/h2&gt;

&lt;p&gt;Python itself is notoriously slow for heavy computations. The interpreter adds overhead, and loops kill performance. That’s why scientific programming in Python always starts with NumPy and SciPy, which wrap C and Fortran under the hood. But even then, scaling to large matrices multiplication (as it happens in multichannel audio) is a challenge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff282198kwffcba3vc45t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff282198kwffcba3vc45t.jpg" alt="python slow meme" width="500" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Already used solutions (and their limitations)
&lt;/h2&gt;

&lt;p&gt;Over the years, developers have tried different hacks to speed up Python:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vectorization with NumPy&lt;/strong&gt; – great, but requires reshaping your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cython&lt;/strong&gt; – lets you drop into C, but you need to rewrite parts of your program.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numba&lt;/strong&gt; – JIT compilation is cool, but not everything is parallelizable, and libraries like SciPy aren’t fully supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these approaches share one problem: you must &lt;strong&gt;refactor your code&lt;/strong&gt; in sometimes &lt;em&gt;not so elegant ways&lt;/em&gt;, and you’re still limited by CPU-based execution (actually numba supports also a simple &lt;a class="mentioned-user" href="https://dev.to/cuda"&gt;@cuda&lt;/a&gt;.jit decorator to run code on an NVIDIA GPU, but even there you often need to add types as in cython and know about cuda kernels).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8de4qnxgz9k96uw45w18.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8de4qnxgz9k96uw45w18.jpg" alt="meme" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PyTorch to the rescue
&lt;/h2&gt;

&lt;p&gt;This is where &lt;strong&gt;PyTorch&lt;/strong&gt; comes in. Originally built for AI, PyTorch provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tensors that work like NumPy arrays, but with GPU acceleration.&lt;/li&gt;
&lt;li&gt;An object-oriented API, more structured than SciPy’s MATLAB-inspired procedural style.&lt;/li&gt;
&lt;li&gt;Direct integration with AI models—any function you write, if you extend the class &lt;code&gt;nn.Module&lt;/code&gt;, can be dropped into a neural network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our paper, we introduce &lt;strong&gt;&lt;a href="https://matteospanio.github.io/torchfx/" rel="noopener noreferrer"&gt;TorchFX&lt;/a&gt;&lt;/strong&gt;, a new library built on top of PyTorch, designed specifically for audio DSP. With TorchFX, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply digital filters and many DSP effects using GPU acceleration.&lt;/li&gt;
&lt;li&gt;Work naturally with &lt;strong&gt;multichannel audio&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Build filter chains with an intuitive &lt;strong&gt;pipe operator (&lt;code&gt;|&lt;/code&gt;)&lt;/strong&gt;, making code both clean and fast (similarly to what happens in &lt;code&gt;langchain&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the performance? In our benchmarks, TorchFX crushed SciPy when dealing with multi-channel or long-duration signals. While SciPy slows down linearly with more channels, TorchFX (especially on GPU) keeps execution times almost flat—even for huge datasets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Python’s slowness has always been the elephant in the room for scientific computing. While solutions like Numba and Cython help, they demand compromises. Our proposal is simple: &lt;strong&gt;if you’re starting from NumPy and SciPy, switch to PyTorch.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With TorchFX, we show how this shift can significantly speed up scientific Python for audio DSP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner, object-oriented code&lt;/li&gt;
&lt;li&gt;Built-in AI compatibility&lt;/li&gt;
&lt;li&gt;GPU acceleration out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? Your code will run blazingly fast.&lt;/p&gt;

&lt;p&gt;TorchFX is open-source and available here: &lt;a href="https://github.com/matteospanio/torchfx" rel="noopener noreferrer"&gt;https://github.com/matteospanio/torchfx&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gpu</category>
      <category>python</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>Avoid the Chaos: How to Properly Manage Python Packages with Virtual Environments</title>
      <dc:creator>Matteo</dc:creator>
      <pubDate>Sun, 30 Jun 2024 09:23:22 +0000</pubDate>
      <link>https://forem.com/matteospanio/pythons-virtual-environments-5fnb</link>
      <guid>https://forem.com/matteospanio/pythons-virtual-environments-5fnb</guid>
      <description>&lt;h2&gt;
  
  
  Managing environments
&lt;/h2&gt;

&lt;p&gt;In embarking on projects, I've learned the hard way that starting without the right tools can lead to wasted time and frustration. This has been evident in my tendency to recklessly install packages, turning my system's Python environment into a chaotic mess. Despite the availability of better alternatives, I've also stuck with the default Python shell. Investing upfront time and effort to avoid these pitfalls can greatly benefit your journey as a Python enthusiast.&lt;/p&gt;

&lt;p&gt;While most programming languages provide a standard library with diverse functionalities, managing additional libraries can be challenging. It's crucial to effectively utilize the standard library, which includes features like file handling, string manipulation, and date/time management. However, to fully leverage Python's capabilities, additional libraries are often required. Python's vibrant developer community produces a plethora of third-party packages, allowing for quick and easy installation. Yet, it's essential to exercise caution and avoid the temptation to install every intriguing package, as it can lead to a chaotic environment where nothing functions properly.&lt;/p&gt;

&lt;p&gt;With this understanding, let's delve into pip, the default package manager tool that accompanies Python installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  pip and virtual environments
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; is Python's package manager. Its name is a recursive acronym that stands for &lt;em&gt;Pip Installs Packages&lt;/em&gt;. &lt;code&gt;pip&lt;/code&gt; is a powerful tool that allows you to install, upgrade, and remove additional libraries, and it is included in Python installation starting from version 3.4.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h5&gt;
  
  
  Legacy Python
&lt;/h5&gt;

&lt;p&gt;If you are using an older version of Python, you can install pip manually. To do so, simply download the &lt;code&gt;get-pip.py&lt;/code&gt; file from the official Python website at &lt;a href="https://bootstrap.pypa.io/get-pip.py"&gt;https://bootstrap.pypa.io/get-pip.py&lt;/a&gt; and run it with Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing packages
&lt;/h3&gt;

&lt;p&gt;To install a Python package using pip, simply use the install command followed by the name of the package. For example, to install the requests package, which is commonly used for making HTTP requests, you would type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pip will then download and install the &lt;a href="https://docs.python-requests.org/en/latest/index.html"&gt;requests package &lt;/a&gt; and any dependencies it requires.&lt;/p&gt;

&lt;p&gt;Now that you have installed requests, you can use it in your Python code by importing it as usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.example.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To uninstall a package that you no longer need, you can use the uninstall command followed by the name of the package. For example, to uninstall the requests package, you would type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip uninstall requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, pip is a simple and straightforward tool for managing Python packages. However, it has one major limitation: it installs packages &lt;strong&gt;globally&lt;/strong&gt;, which can lead to conflicts between different projects that require different versions of the same package.&lt;/p&gt;

&lt;p&gt;To avoid these conflicts, it is best to use &lt;strong&gt;virtual environments&lt;/strong&gt;. A virtual environment is an isolated environment that contains its own Python interpreter and its own set of installed packages. This allows you to work on multiple projects with different dependencies without worrying about conflicts. Python provides a built-in module called &lt;a href="https://docs.python.org/3/library/venv.html"&gt;venv&lt;/a&gt; that allows you to create and manage virtual environments. To create a new virtual environment, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv myenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new directory called &lt;code&gt;myenv&lt;/code&gt; that contains a copy of the Python interpreter and a copy of the &lt;code&gt;pip&lt;/code&gt; package manager.&lt;br&gt;
Let's look in detail at the folder structure of the virtual environment with the shell utility &lt;code&gt;tree&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nt"&gt;-L&lt;/span&gt; 4 myenv

myenv
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── Activate.ps1
│   ├── pip
│   ├── pip3
│   ├── pip3.10
│   ├── python -&amp;gt; python3
│   ├── python3 -&amp;gt; /usr/bin/python3
│   └── python3.10 -&amp;gt; python3
├── include
├── lib
│   └── python3.10
│       └── site-packages
│           ├── _distutils_hack
│           ├── distutils-precedence.pth
│           ├── pip
│           ├── pip-22.0.2.dist-info
│           ├── pkg_resources
│           ├── setuptools
│           └── setuptools-59.6.0.dist-info
├── lib64 -&amp;gt; lib
└── pyvenv.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see the &lt;code&gt;bin&lt;/code&gt; directory contains the &lt;code&gt;activate&lt;/code&gt; script that allows you to activate the virtual environment. The &lt;code&gt;lib&lt;/code&gt; directory contains the installed packages, and the &lt;code&gt;include&lt;/code&gt; directory contains the header files needed to compile C extensions. The &lt;code&gt;pyvenv.cfg&lt;/code&gt; file contains the configuration of the virtual environment.&lt;/p&gt;

&lt;p&gt;To activate the virtual environment, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;myenv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will activate the virtual environment, and you will see the name of the virtual environment in your shell prompt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h5&gt;
  
  
  TIP
&lt;/h5&gt;

&lt;p&gt;On Windows, the command to activate the virtual environment is slightly different:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;myenv&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Once the virtual environment is activated, any packages you install using &lt;code&gt;pip&lt;/code&gt; will be installed in the virtual environment rather than globally. This allows you to work on your project without worrying about conflicts with other projects.&lt;/p&gt;

&lt;p&gt;For example, to install the requests package in the virtual environment, you would type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but this time the package will be installed in the &lt;code&gt;myenv&lt;/code&gt; directory rather than globally. In fact if you look at the &lt;code&gt;lib&lt;/code&gt; directory of the virtual environment you will see the installed packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nt"&gt;-L&lt;/span&gt; 1 myenv/lib/python3.10/site-packages

myenv/lib/python3.10/site-packages
├── certifi
├── certifi-2024.6.2.dist-info
├── charset_normalizer
├── charset_normalizer-3.3.2.dist-info
├── _distutils_hack
├── distutils-precedence.pth
├── idna
├── idna-3.7.dist-info
├── pip
├── pip-22.0.2.dist-info
├── pkg_resources
├── requests
├── requests-2.32.3.dist-info
├── setuptools
├── setuptools-59.6.0.dist-info
├── urllib3
└── urllib3-2.2.2.dist-info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you are finished working on your project, you can deactivate the virtual environment using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return you to the global Python environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing requirements
&lt;/h3&gt;

&lt;p&gt;When working on a project, it is common to have a list of required packages that need to be installed. This list is often stored in a file called &lt;code&gt;requirements.txt&lt;/code&gt;, which can be used to install all the required packages at once. To create a &lt;code&gt;requirements.txt&lt;/code&gt; file, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;requirements.txt&lt;/code&gt; file that contains a list of all the packages installed in the current environment. To install the packages listed in a &lt;code&gt;requirements.txt&lt;/code&gt; file, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install all the packages listed in the &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  pipx
&lt;/h2&gt;

&lt;p&gt;Sometimes, you may want to install a Python application that is not a library, but a standalone program. In this case, you can use &lt;code&gt;pipx&lt;/code&gt;. &lt;code&gt;pipx&lt;/code&gt; is a tool that allows you to install and manage Python applications in an isolated environment. This means that when you install an application with &lt;code&gt;pipx&lt;/code&gt;, it is not installed in the system, but in a dedicated virtual environment. This allows you to avoid conflicts between different versions of libraries and keep your system clean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;package_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To uninstall a package installed with &lt;code&gt;pipx&lt;/code&gt;, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx uninstall &amp;lt;package_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to note that &lt;code&gt;pipx&lt;/code&gt; is not a replacement for &lt;code&gt;pip&lt;/code&gt;. It is a complementary tool that is used specifically for installing and managing Python applications. If you want to install a library, you should use &lt;code&gt;pip&lt;/code&gt; instead. &lt;code&gt;pipx&lt;/code&gt; is particularly useful for installing command-line tools that are written in Python, such as &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;flake8&lt;/code&gt;, &lt;code&gt;isort&lt;/code&gt;, and many others that you will likely to use transversally in your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  conda
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;conda&lt;/code&gt; is an open-source package management system and environment management system that runs on Windows, macOS, and Linux. It is a powerful tool that allows you to create and manage virtual environments, install and update packages, and manage dependencies. &lt;code&gt;conda&lt;/code&gt; is particularly popular in the scientific computing community, as it provides access to a wide range of scientific computing libraries and tools. I suggest to have a look at the official documentation at &lt;a href="https://docs.conda.io/en/latest/"&gt;https://docs.conda.io/en/latest/&lt;/a&gt; to get started with &lt;code&gt;conda&lt;/code&gt;. An important thing to note is that &lt;code&gt;conda&lt;/code&gt; has its own way to install packages through the &lt;code&gt;conda install&lt;/code&gt; command, which is different from &lt;code&gt;pip&lt;/code&gt;. This is because &lt;code&gt;conda&lt;/code&gt; manages its own package repositories, which are separate from the Python Package Index (PyPI). This means that some packages may be available on &lt;code&gt;conda&lt;/code&gt; but not on PyPI, and vice versa, anyway &lt;code&gt;conda&lt;/code&gt; can install packages from PyPI as well using the &lt;code&gt;pip&lt;/code&gt; package manager.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;conda&lt;/code&gt; solves the virtual environment problem its own way, it lets you create and activate virtual environments creating them for you. When you install &lt;code&gt;conda&lt;/code&gt; for the first time it comes with a default virtual environment called &lt;code&gt;base&lt;/code&gt;. As stated before a good practice is to create a virtual environment for each project, anyway the &lt;code&gt;conda&lt;/code&gt; design encourages you to reuse a virtual environment. For example, you can create a virtual environment called &lt;code&gt;torch&lt;/code&gt; and install the &lt;code&gt;torch&lt;/code&gt; package in it, then you can create another virtual environment called &lt;code&gt;tensorflow&lt;/code&gt; and install the &lt;code&gt;tensorflow&lt;/code&gt; package in it. This way you can switch between the two environments when you need to work on a project that requires &lt;code&gt;torch&lt;/code&gt; or &lt;code&gt;tensorflow&lt;/code&gt;. This is a different approach from &lt;code&gt;venv&lt;/code&gt; where you create a new virtual environment for each project. If you find yourself working on multiple projects that require the same set of packages, &lt;code&gt;conda&lt;/code&gt; can be a good choice for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  poetry &amp;amp; friends
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;poetry&lt;/code&gt; is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you. It also allows you to specify the Python version and the Python interpreter to use. &lt;code&gt;poetry&lt;/code&gt; is particularly popular in the data science community, as it provides a simple and powerful way to manage dependencies and package your projects. This tool is really similar to &lt;code&gt;npm&lt;/code&gt; in the JavaScript world, or &lt;code&gt;cargo&lt;/code&gt; in the Rust world, and it is a great way to manage your Python projects. You can find more information about &lt;code&gt;poetry&lt;/code&gt; at &lt;a href="https://python-poetry.org/"&gt;https://python-poetry.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the most interesting features of &lt;code&gt;poetry&lt;/code&gt;, in my opinion, is the fact that you are &lt;em&gt;enforced&lt;/em&gt; to organize your project in a specific way. This is because &lt;code&gt;poetry&lt;/code&gt; expects your project to have a specific structure, with a &lt;code&gt;pyproject.toml&lt;/code&gt; file that contains the project's metadata and dependencies. This makes it easier to manage your project and share it with others, as they will know exactly where to find the project's dependencies and how to install them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;poetry&lt;/code&gt; is not the only tool in this category. Other popular tools include &lt;code&gt;pipenv&lt;/code&gt; and &lt;code&gt;pip-tools&lt;/code&gt;. Each of these tools has its own strengths and weaknesses, and the best tool for you will depend on your specific needs and preferences.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>productivity</category>
      <category>development</category>
    </item>
    <item>
      <title>Python's Static Typing Safari: In Search of Code Clarity</title>
      <dc:creator>Matteo</dc:creator>
      <pubDate>Sun, 12 Nov 2023 12:12:37 +0000</pubDate>
      <link>https://forem.com/matteospanio/pythons-static-typing-safari-in-search-of-code-clarity-1bnb</link>
      <guid>https://forem.com/matteospanio/pythons-static-typing-safari-in-search-of-code-clarity-1bnb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the vast landscape of programming languages, Python stands out as a dynamically typed language, celebrated for its readability and simplicity. Its syntax, clear and concise, makes it an ideal choice for scripting and automating processes with just a few lines of code. However, as projects grow in complexity and involve multiple contributors, the need for a more robust syntax becomes evident.&lt;/p&gt;

&lt;p&gt;In this exploration, we dive into the realm of Python's static typing, unraveling its nuances and unveiling the tools at our disposal. Beyond the simplicity of dynamically typed languages, Python provides features like type annotations, function overloading, and generics, offering developers a sophisticated toolkit for crafting elegant and maintainable code.&lt;/p&gt;

&lt;p&gt;Let's embark on a journey through the evolution of a simple addition function, uncovering the power of type annotations, the resurgence of overloading, and the elegance introduced by generics in Python. Join us as we navigate the intricacies of Python's static typing, discovering how it transforms code clarity and enhances the development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug alert!
&lt;/h2&gt;

&lt;p&gt;Consider the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function sums two elements. In this case, it might seem reasonable to leave it as it is, as you get function overloading for free on types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# a: int,   b: int   -&amp;gt; int
&lt;/span&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# a: float, b: float -&amp;gt; float
&lt;/span&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# a: int,   b: float -&amp;gt; float
&lt;/span&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mf"&gt;2.3j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# a: int, b: complex -&amp;gt; complex
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the calls to the &lt;code&gt;mysum&lt;/code&gt; function are correct, and each time Python is able to infer the correct return type. Similarly, these function calls are valid and correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, what happens when you start calling the function with mixed arguments?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These lines are legitimate Python, yet most text editors won't complain. However, once the script executes, the Python interpreter crashes against these type mismatches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Traceback (most recent call last):
&lt;/span&gt;&lt;span class="gp"&gt;  File "&amp;lt;stdin&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;", line 1, in &amp;lt;module&amp;gt;
&lt;/span&gt;&lt;span class="gp"&gt;  File "&amp;lt;stdin&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, line 2, &lt;span class="k"&gt;in &lt;/span&gt;mysum
&lt;span class="go"&gt;TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type annotations
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;TypeError&lt;/code&gt;! How is this possible?! Who dared to tell the interpreter to check types? Even though the use of types in Python is mostly transparent, it doesn't mean they don't exist. Therefore, annotating types in Python can be a good idea to save hours of debugging. Consider the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the code above. The first function, &lt;code&gt;mysum_number&lt;/code&gt;, accepts two arguments of type &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, or &lt;code&gt;complex&lt;/code&gt; and returns a value of the same type. The second function, &lt;code&gt;mysum_list&lt;/code&gt;, accepts two arguments of type &lt;code&gt;list&lt;/code&gt; and returns a value of the same type. The third function, &lt;code&gt;mysum_str&lt;/code&gt;, accepts two arguments of type &lt;code&gt;str&lt;/code&gt; and returns a value of the same type.&lt;/p&gt;

&lt;p&gt;Now, every time you want to add two elements, knowing their type is enough to decide which function to call. However, this precision sacrifices overloading. To call all functions in the same way, indicating the desire for an overload, the standard library &lt;code&gt;typing&lt;/code&gt; contains the &lt;code&gt;overload&lt;/code&gt; decorator. The refactored code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;overload&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;overload&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;overload&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;overload&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overloading is back. Now, the function calls seen earlier all work, and those that used to generate a &lt;code&gt;TypeError&lt;/code&gt; at runtime are now highlighted in red by our IDE.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The three dots &lt;code&gt;...&lt;/code&gt; have a special meaning in Python; it is the symbol known as an &lt;em&gt;ellipsis&lt;/em&gt;. This symbol is usually used as a placeholder, but its meaning can vary slightly depending on the context. I recommend checking the documentation if you are curious and want to understand more about it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Generics
&lt;/h2&gt;

&lt;p&gt;We could consider ourselves satisfied like this, but the &lt;code&gt;typing&lt;/code&gt; module offers many other features. Among these, the use of Generics stands out, which in this case can be exploited to create a more elegant solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;

&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"T"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;TypeVar&lt;/code&gt; allows you to define a type that varies depending on the context, but once it is determined, it cannot change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# T = int
&lt;/span&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# T = float
&lt;/span&gt;&lt;span class="n"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"b"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# T = str
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since Python 3.12 the &lt;code&gt;T&lt;/code&gt; typevar declaration can be omitted&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, and the type can be directly specified in the function definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mysum&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)](&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Along with &lt;code&gt;T&lt;/code&gt; some constraints have been added, which are the types that &lt;code&gt;T&lt;/code&gt; can assume. In this case, &lt;code&gt;T&lt;/code&gt; can be &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;complex&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, or &lt;code&gt;list&lt;/code&gt;. That's because the &lt;code&gt;+&lt;/code&gt; operator is defined for these types and not for others.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Sum up
&lt;/h2&gt;

&lt;p&gt;In this exploration of Python's static typing, we delved into crucial concepts that enhance code clarity and maintainability. Let's recap the key takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Syntax for All Sizes:&lt;/strong&gt; Python's dynamic typing shines in small scripts, offering a clear and concise syntax. However, as projects grow, the need for a more expressive syntax becomes apparent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigating Overloading:&lt;/strong&gt; The journey from a dynamically typed function to an overloaded one, thanks to the &lt;code&gt;typing&lt;/code&gt; module's &lt;code&gt;overload&lt;/code&gt; decorator, showcases Python's adaptability to diverse project requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type Annotations as Guides:&lt;/strong&gt; Embracing type annotations is akin to providing a map for your code. Explicitly specifying types not only aids in debugging but also serves as documentation, making your code more understandable and maintainable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generics: The Elegance Factor:&lt;/strong&gt; The introduction of generics via &lt;code&gt;TypeVar&lt;/code&gt; elevates Python's static typing to new heights. With constraints on acceptable types, developers can craft more elegant and type-safe solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evolution of Python's Typing Tools:&lt;/strong&gt; From annotations to overloading and generics, Python's typing tools evolve to cater to various development scenarios, offering a versatile toolkit for developers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you navigate your coding endeavors, remember that Python's static typing is not about rigid constraints but about providing developers with powerful tools to enhance their code's expressiveness and robustness. Embrace these tools judiciously, and may your coding journey be both clear and elegant.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0695/"&gt;PEP 695 -- Type Parameter Syntax&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>python</category>
      <category>typing</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
