<?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>DEV Community: Aliaksandr Valshtein</title>
    <description>The latest articles on DEV Community by Aliaksandr Valshtein (@tilalis).</description>
    <link>https://dev.to/tilalis</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%2F387922%2F5b038f9e-f7cd-4353-b158-f2b237a53bcd.jpeg</url>
      <title>DEV Community: Aliaksandr Valshtein</title>
      <link>https://dev.to/tilalis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tilalis"/>
    <language>en</language>
    <item>
      <title>Optimize Python Sorting with One Little Trick</title>
      <dc:creator>Aliaksandr Valshtein</dc:creator>
      <pubDate>Wed, 19 Nov 2025 20:54:23 +0000</pubDate>
      <link>https://dev.to/tilalis/optimize-python-sorting-with-one-little-trick-2gb</link>
      <guid>https://dev.to/tilalis/optimize-python-sorting-with-one-little-trick-2gb</guid>
      <description>&lt;p&gt;TL;DR&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="c1"&gt;# if we have a class like this
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="c1"&gt;# in a big enough list
&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book&lt;/span&gt;&lt;span class="sh"&gt;"&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="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pencil&lt;/span&gt;&lt;span class="sh"&gt;"&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="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book&lt;/span&gt;&lt;span class="sh"&gt;"&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="p"&gt;...]&lt;/span&gt;

&lt;span class="c1"&gt;# this sorting will be faster
&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# than this
&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Well...&lt;/p&gt;

&lt;p&gt;One of the things Python makes really simple is sorting.&lt;/p&gt;

&lt;p&gt;You can easily find the answer to the question &lt;a href="https://stackoverflow.com/questions/10948920/what-algorithm-does-pythons-sorted-use" rel="noopener noreferrer"&gt;"how sorting is implemented in Python?"&lt;/a&gt; which almost always answers another question: "What sorting algorithm does Python use?". &lt;/p&gt;

&lt;p&gt;The answer often leaves one detail behind. An optimization introduced in &lt;a href="https://docs.python.org/3.12/whatsnew/3.7.html" rel="noopener noreferrer"&gt;python 3.7&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3.12/library/functions.html#sorted" rel="noopener noreferrer"&gt;&lt;code&gt;sorted()&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.python.org/3.12/library/stdtypes.html#list.sort" rel="noopener noreferrer"&gt;&lt;code&gt;list.sort()&lt;/code&gt;&lt;/a&gt; have been optimized for common cases to be up to 40-75% faster. (Contributed by Elliot Gorokhovsky in &lt;a href="https://bugs.python.org/issue?@action=redirect&amp;amp;bpo=28685" rel="noopener noreferrer"&gt;bpo-28685&lt;/a&gt;.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But before we dig into that...&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief Re-introduction to Sorting in Python
&lt;/h2&gt;

&lt;p&gt;If you want to sort a list in python, you have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A list method: &lt;a href="https://docs.python.org/3/tutorial/datastructures.html#more-on-lists" rel="noopener noreferrer"&gt;list.sort(*, key=None, reverse=False)&lt;/a&gt;, which sorts the given list in-place&lt;/li&gt;
&lt;li&gt;A built-in function: &lt;a href="https://docs.python.org/3/library/functions.html#sorted" rel="noopener noreferrer"&gt;sorted(&lt;em&gt;iterable&lt;/em&gt;, &lt;em&gt;/&lt;/em&gt;, &lt;em&gt;*&lt;/em&gt;, &lt;em&gt;key=None&lt;/em&gt;, &lt;em&gt;reverse=False&lt;/em&gt;)&lt;/a&gt;, which returns a sorted list without modifying its argument&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For any other built-in iterable, you can only use &lt;code&gt;sorted&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sorted&lt;/code&gt; always returns a list because it uses &lt;code&gt;list.sort&lt;/code&gt; internally.&lt;/p&gt;

&lt;p&gt;Here is a rough equivalent of CPython's &lt;code&gt;sorted&lt;/code&gt; C implementation rewritten in pure python:&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;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;new_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reverse&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;new_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, it's that simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  How  Python Makes Sorting Faster
&lt;/h2&gt;

&lt;p&gt;As Python's &lt;a href="https://github.com/python/cpython/blob/main/Objects/listsort.txt#L820-L822" rel="noopener noreferrer"&gt;internal documentation for sorting&lt;/a&gt; puts it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is sometimes possible to substitute faster type-specific comparisons for the slower, generic PyObject_RichCompareBool&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And in short this optimization can be described as follows: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a list is homogeneous, Python uses &lt;strong&gt;type-specific comparison function&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What Is a Homogeneous List?
&lt;/h3&gt;

&lt;p&gt;A homogeneous list is a list that contains elements only of one type.&lt;/p&gt;

&lt;p&gt;For example:&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;homogeneous&lt;/span&gt; &lt;span class="o"&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;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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, this is not a homogeneous list:&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;heterogeneous&lt;/span&gt; &lt;span class="o"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;&lt;span class="sh"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.python.org/3/tutorial/datastructures.html" rel="noopener noreferrer"&gt;Official Python tutorial&lt;/a&gt; also mentions the difference:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lists are mutable, and their elements are &lt;strong&gt;usually homogeneous&lt;/strong&gt; and are accessed by iterating over the list&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  A side note about tuples
&lt;/h4&gt;

&lt;p&gt;That same tutorial states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tuples are &lt;a href="https://docs.python.org/3/glossary.html#term-immutable" rel="noopener noreferrer"&gt;immutable&lt;/a&gt;, and &lt;strong&gt;usually contain a heterogeneous sequence&lt;/strong&gt; of elements&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if you ever wonder when to use a tuple or a list here's a rule of thumb: If the elements are of the same type, use a list. Otherwise use a tuple.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wait, and what about &lt;code&gt;array&lt;/code&gt;s ?
&lt;/h4&gt;

&lt;p&gt;Python implements a homogeneous &lt;a href="https://docs.python.org/3/library/array.html" rel="noopener noreferrer"&gt;array&lt;/a&gt; container object for numeric values.&lt;/p&gt;

&lt;p&gt;However, as of python 3.14, arrays do not implement their own &lt;code&gt;sort&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;The only way to sort them is by using &lt;code&gt;sorted&lt;/code&gt;, which internally creates a list out of the array, erasing any type-related information in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Using Type-Specific Comparison Function Helps?
&lt;/h2&gt;

&lt;p&gt;Comparisons in python are costly, because Python performs various checks before doing any actual comparison.&lt;/p&gt;

&lt;p&gt;Here is a &lt;em&gt;simplified&lt;/em&gt; explanation of what happens under the hood when you compare two values in python:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python checks that the values passed to comparison function are not &lt;code&gt;NULL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If values are of different types, but right operand is a subtype of the left, Python uses right operand's comparison function, but reversed (e.g., it will use &lt;code&gt;&amp;lt;&lt;/code&gt; for &lt;code&gt;&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;If the values are of the same type, or different types but neither is a subtype of the other:

&lt;ul&gt;
&lt;li&gt;Python will first try left operand's comparison function&lt;/li&gt;
&lt;li&gt;If that fails, it will try right operand's comparison function, but reversed.&lt;/li&gt;
&lt;li&gt;If that fails too, and the comparison is for equality or inequality, it will return identity comparison (True for values that refer to the same object in memory)&lt;/li&gt;
&lt;li&gt;Otherwise, it raises &lt;code&gt;TypeError&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2F9fst0q6xzb97zcitkfv2.png" 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%2F9fst0q6xzb97zcitkfv2.png" alt="How Python Compares Two Values" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On top of this, each type's own comparison functions implement additional checks.&lt;/p&gt;

&lt;p&gt;For example, when comparing strings, Python will check if the string characters take more than one byte of memory, and float comparison will compare a pair of &lt;code&gt;float&lt;/code&gt;'s and a &lt;code&gt;float&lt;/code&gt; and an &lt;code&gt;int&lt;/code&gt; differently.&lt;/p&gt;

&lt;p&gt;A more detailed explanation and diagram can be found here: &lt;a href="https://github.com/embg/python-fastsort-benchmark/blob/master/poster.pdf" rel="noopener noreferrer"&gt;Adding Data-Aware Sort Optimizations to CPython&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before this optimization was introduced, Python had to execute all this various type-specific and non-type-specific checks every time two values were compared during sorting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking List Element's Types in Advance
&lt;/h2&gt;

&lt;p&gt;There's no magical way to know if all the elements of a list are of the same type other than to iterate over the list and check each  element.&lt;/p&gt;

&lt;p&gt;Python does almost exactly that — checking the types of sorting keys generated by &lt;code&gt;key&lt;/code&gt; function passed to &lt;code&gt;list.sort&lt;/code&gt; or &lt;code&gt;sorted&lt;/code&gt; as a parameter&lt;/p&gt;

&lt;h2&gt;
  
  
  Constructing a List of Keys
&lt;/h2&gt;

&lt;p&gt;If a &lt;code&gt;key&lt;/code&gt; function is provided, Python uses it to construct a list of keys, otherwise it uses the &lt;code&gt;list&lt;/code&gt;'s own values as sorting keys.&lt;/p&gt;

&lt;p&gt;In an oversimplified manner, keys construction can be expressed as the following python 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;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list_items&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;list_item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;list_item&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note, that &lt;code&gt;keys&lt;/code&gt; used internally in CPython are a C array of CPython object references, and not a Python list&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the keys are constructed, Python checks their types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Key's Type
&lt;/h3&gt;

&lt;p&gt;When checking the types of keys, Python's sorting algorithm tries to determine if all elements in the keys array are either &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt; or &lt;code&gt;tuple&lt;/code&gt;, or simply of the same type, with some constraints for base types.&lt;/p&gt;

&lt;p&gt;It's worth noting that checking the types of the keys adds some extra work up front. Python does this because it usually pays off by making the actual sorting faster, especially for longer lists.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;int&lt;/code&gt; constraints
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;int&lt;/code&gt; should &lt;strong&gt;not&lt;/strong&gt; be a bignum&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Practically this means that for this optimization to work, integer should be less than &lt;em&gt;2^30 - 1&lt;/em&gt; (this may vary depending on the platform)  &lt;/p&gt;

&lt;p&gt;As a side note, here is a great article which explains how Python handles big integers: &lt;a href="https://www.codementor.io/@arpitbhayani/how-python-implements-super-long-integers-12icwon5vk" rel="noopener noreferrer"&gt;# How python implements super long integers?&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;str&lt;/code&gt; constraints
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;All characters of a string should take less than 1 byte of memory, meaning that they should be represented by integer values in the range of 0-255&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In practice, this means that strings should consist only of Latin characters, spaces, and some special characters found in the ASCII table.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;float&lt;/code&gt; constraints
&lt;/h4&gt;

&lt;p&gt;There are no constraints for floats in order for this optimization to work.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;tuple&lt;/code&gt; constraints
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Only the first element's type is checked&lt;/li&gt;
&lt;li&gt;This element itself should not be a tuple itself&lt;/li&gt;
&lt;li&gt;If all tuples share the same type for their first element, the comparison optimization is applied to them&lt;/li&gt;
&lt;li&gt;All other elements are compared as usual&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Can I Apply This Knowledge?
&lt;/h2&gt;

&lt;p&gt;First of all, isn’t it fascinating to know?&lt;/p&gt;

&lt;p&gt;Secondly, mentioning this knowledge could be a nice touch in a Python Developer interview.&lt;/p&gt;

&lt;p&gt;As for actual code development, understanding this optimization can help you improve sorting performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimize by Selecting the Type of Values Wisely
&lt;/h3&gt;

&lt;p&gt;According to the benchmark in the &lt;a href="https://github.com/python/cpython/pull/582" rel="noopener noreferrer"&gt;PR that introduced this optimization&lt;/a&gt;, sorting a list that consists only of floats rather than a list of floats with even a single integer at the end is almost twice as fast.&lt;/p&gt;

&lt;p&gt;So when it's time to optimize, transforming list 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="n"&gt;floats_and_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Into list that 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="n"&gt;just_floats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&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;3.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# note that 3.0 is a float now
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might improve performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimize by Using Keys for Lists of Objects
&lt;/h3&gt;

&lt;p&gt;While Python's sorting optimization works well with built-in types, it's important to understand how it interacts with custom classes. &lt;/p&gt;

&lt;p&gt;When sorting objects of custom classes, Python relies on the comparison methods you define, such as &lt;code&gt;__lt__&lt;/code&gt; (less than) or &lt;code&gt;__gt__&lt;/code&gt; (greater than). &lt;/p&gt;

&lt;p&gt;However, the type-specific optimization doesn't apply to custom classes. &lt;br&gt;
Python will always use the general comparison method for these objects.&lt;/p&gt;

&lt;p&gt;Here's an example:&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;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&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;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__lt__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; 

&lt;span class="n"&gt;my_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;MyClass&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="nc"&gt;MyClass&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="nc"&gt;MyClass&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="n"&gt;sorted_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, Python will use the &lt;code&gt;__lt__&lt;/code&gt; method for comparisons, but it won't benefit from the type-specific optimization. The sorting will still work correctly, but it may not be as fast as sorting built-in types.&lt;/p&gt;

&lt;p&gt;If performance is critical when sorting custom objects, consider using a key function that returns a built-in type:&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;sorted_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Afterword
&lt;/h2&gt;

&lt;p&gt;Premature optimization, especially in Python, is evil. &lt;/p&gt;

&lt;p&gt;You should not design your entire application around specific optimizations in CPython, but it’s good to be aware of these optimizations: knowing your tools well is a way of becoming a more skilled developer. &lt;/p&gt;

&lt;p&gt;Being mindful of optimizations like these allows you to take advantage of them when the situation calls for it, especially when performance becomes critical: &lt;/p&gt;

&lt;p&gt;Consider a scenario where were your sorting is based on timestamps: using a homogeneous list of integers (Unix timestamps) instead of datetime objects could leverage this optimization effectively.&lt;/p&gt;

&lt;p&gt;However, it's crucial to remember that code readability and maintainability should take precedence over such optimizations. &lt;/p&gt;

&lt;p&gt;While it's important to know about these low-level details, it is as much important to appreciate Python's high-level abstractions that make it such a productive language.&lt;/p&gt;

</description>
      <category>python</category>
      <category>sorting</category>
      <category>learning</category>
      <category>internals</category>
    </item>
    <item>
      <title>Git Extension to handle multiple repositories easily</title>
      <dc:creator>Aliaksandr Valshtein</dc:creator>
      <pubDate>Fri, 09 Feb 2024 15:21:07 +0000</pubDate>
      <link>https://dev.to/tilalis/git-extension-to-handle-multiple-repositories-easily-a9f</link>
      <guid>https://dev.to/tilalis/git-extension-to-handle-multiple-repositories-easily-a9f</guid>
      <description>&lt;p&gt;The sad reality of software development is that not everyone uses git submodules, and dealing with multiple interconnected repositories can be tedious. &lt;/p&gt;

&lt;p&gt;Naturally, a whole class of git extensions exists to solve this problem.&lt;/p&gt;

&lt;p&gt;None of them suited me, so I created my own!&lt;/p&gt;

&lt;p&gt;Generally, it's a good idea to use submodules or subtrees, but usually whether to use it or not is not up to you.&lt;/p&gt;

&lt;p&gt;So I came up with a simple git extension to handle multiple repositories in bulk. &lt;/p&gt;

&lt;p&gt;I present to you &lt;a href="https://github.com/tilalis/git-all"&gt;git-all&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's assume that you have the following directory structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-awesome-repositories/
    my-awesome-repo-1/ # this is a git repository
    my-awesome-repo-2/ # that's another git repository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing &lt;code&gt;git all status&lt;/code&gt; inside &lt;code&gt;my-awesome-repositories&lt;/code&gt; directory is the exact equivalent of executing the following bash commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-awesome-repo-1
git status
cd ..

cd my-awesome-repo-2
git status
cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What can I do with it?
&lt;/h2&gt;

&lt;p&gt;Whatever you want! Generally, &lt;em&gt;almost&lt;/em&gt; everything you type after &lt;code&gt;all&lt;/code&gt; will be passed to &lt;code&gt;git&lt;/code&gt; unchanged. &lt;/p&gt;

&lt;p&gt;The syntax is &lt;code&gt;git all {basically any other git command}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Basically, you can do whatever &lt;code&gt;git&lt;/code&gt; can do.&lt;/p&gt;

&lt;p&gt;A couple of examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git all tag -a v1 -m "release"&lt;/code&gt; — this command tags all commits of every repository in the current subfolder with v1 tag and "release" tag message&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;git all push origin master&lt;/code&gt; — this one will push from all   repositories in the current subfolder to branch master on the origin remote &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What about cloning?
&lt;/h2&gt;

&lt;p&gt;The only different thing about git all is cloning, but, instead of repository name you just need to provide a file where every line is an argument to regular &lt;code&gt;git clone&lt;/code&gt;, and that's &lt;strong&gt;all&lt;/strong&gt; (pun intended).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat myrepo.list
--branch master https://github.com/stencila/test.git 
https://github.com/rtyley/small-test-repo.git
$ git all clone myrepo.list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it's different from similar extensions?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It's just a simple bash script, similar to one you could have written yourself&lt;/li&gt;
&lt;li&gt;It's zero-configuration, you don't need to register directories, create workspaces and configuration files&lt;/li&gt;
&lt;li&gt;It's written in bash, so you don't need to use Node.js or python&lt;/li&gt;
&lt;li&gt;You don't need to learn how to use it, it's just your regular git commands&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>bash</category>
      <category>tutorial</category>
      <category>development</category>
    </item>
  </channel>
</rss>
