{"id":58623,"date":"2024-01-30T03:38:22","date_gmt":"2024-01-30T03:38:22","guid":{"rendered":"https:\/\/www.askpython.com\/?p=58623"},"modified":"2025-04-10T20:43:03","modified_gmt":"2025-04-10T20:43:03","slug":"python-hashable-objects","status":"publish","type":"post","link":"https:\/\/www.askpython.com\/python-modules\/python-hashable-objects","title":{"rendered":"Python Hashable Objects: Learning the Key Concepts"},"content":{"rendered":"\n<p>In Python, the term \u201chashable\u201d refers to any object with a hash value that never changes during its lifetime. This hash value allows hashable objects to be used as dictionary keys or as members of sets, providing fast lookup and comparison operations.<\/p>\n\n\n\n<p>But what exactly does it mean for an object to be hashable, and why does it matter? Let\u2019s break it down step-by-step.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>A hashable object is one with a consistent hash value throughout its lifetime, enabling its use as dictionary keys or set members. Hashable objects include immutable types like integers, strings, tuples, while lists, dictionaries, and sets are non-hashable due to their mutability. Understanding hashability is crucial for efficient data storage and retrieval in Python, as it ensures fast and reliable access in data structures like hash tables.<\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hash-functions-in-python\">Exploring Python&#8217;s Hash Functions<\/h2>\n\n\n\n<p>A&nbsp;<strong>hash function<\/strong>&nbsp;is a function that takes input data of arbitrary size, and converts it into a fixed size value. This value is called the hash value or hash. A good hash function has some key properties:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It generates very different hash values for similar input values &#8211; even a small change in the input results in a large change in the hash. This is called&nbsp;the <strong>avalanche effect<\/strong>.<\/li>\n\n\n\n<li>It uniformly distributes hashes across the possible output range for the hash function.<\/li>\n\n\n\n<li>It is deterministic &#8211; the same input value will always generate the same hash value.<\/li>\n<\/ul>\n\n\n\n<p>Python has a built-in&nbsp;<code>hash()<\/code>&nbsp;function that can generate hash values:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; hash(&quot;Python&quot;) \n7282735233108043601\n\n<\/pre><\/div>\n\n\n<p>The actual algorithm used by&nbsp;<code>hash()<\/code>&nbsp;can vary between Python versions, but the properties stay the same.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"why-hashing-is-useful\">Why Hashing is Useful<\/h2>\n\n\n\n<p>Generating hash values allows us to compare dictionary keys or set members quickly.<\/p>\n\n\n\n<p>For example, let\u2019s say we wanted to check if two lists contain the same elements. Without hashing, we would need to iterate through both lists and check each element, which takes linear time O(n).<\/p>\n\n\n\n<p>But if the lists contain hashable items like strings or tuples, we can simply hash each list and compare the hashes in constant O(1) time:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ndef list_equals(list1, list2):\n    return hash(tuple(list1)) == hash(tuple(list2))\n\n<\/pre><\/div>\n\n\n<p>By using the hash, we no longer care if the lists are ordered differently. All we care about is whether they hash to the same value.<\/p>\n\n\n\n<p>This speedup via hashing applies to dictionaries and sets as well. Python actually stores set items and dictionary keys in a hash table internally to enable fast lookups.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hashable-objects-in-python\">Hashable Objects in Python<\/h2>\n\n\n\n<p>For an object to be hashable, two key requirements must be met:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. It must have a\u00a0hash\u00a0method that returns an integer.<\/h3>\n\n\n\n<p>All Python objects inherit a&nbsp;<code>__hash__<\/code>&nbsp;method, but for mutable objects like lists and dicts,&nbsp;<code>__hash__<\/code>&nbsp;returns a TypeError indicating that the object is unhashable.<\/p>\n\n\n\n<p>For immutable built-in objects like integers, strings and tuples,&nbsp;<code>__hash__<\/code>&nbsp;returns a unique integer derived from the object\u2019s value:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; hash(&quot;hello&quot;)\n1859319527393798429\n\n&gt;&gt;&gt; hash( (&quot;apple&quot;, &quot;banana&quot;)) \n8424618783216606276\n<\/pre><\/div>\n\n\n<p>Custom classes are hashable by default if you don\u2019t override&nbsp;<code>__hash__<\/code>, but best practice is to implement it explicitly if defining custom equality behavior with&nbsp;<code>__eq__<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Its hash value cannot change while it is in use by a dict or set.<\/h3>\n\n\n\n<p>That\u2019s why only immutable objects can be hashable &#8211; they guarantee their hash value will not change over their lifetime. A tuple object will always hash to the same value. But if a list was hashable, appending items would change its content while still expecting lookups based on the old hash value.<\/p>\n\n\n\n<p>An object is hashable if:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It supports hash() via a&nbsp;<strong>hash<\/strong>() method<\/li>\n\n\n\n<li>Its hash value is immutable and stays constant over the lifetime of the object<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"trying-to-hash-mutable-objects\">The Challenge of Hashing Mutable Objects<\/h2>\n\n\n\n<p>If we try to get the hash value of a mutable object like a list, set, or <a href=\"https:\/\/www.askpython.com\/python\/dictionary\/python-dictionary-dict-tutorial\" data-type=\"post\" data-id=\"535\">dict<\/a>, we get a TypeError:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; hash(&#x5B;1,2,3])\nTraceback (most recent call last):\n  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;\nTypeError: unhashable type: &#039;list&#039;\n\n&gt;&gt;&gt; hash({1: &quot;one&quot;})\nTraceback (most recent call last):\n  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;\nTypeError: unhashable type: &#039;dict&#039; \n\n<\/pre><\/div>\n\n\n<p>We can even put a mutable list inside an immutable tuple, and it still won\u2019t be hashable because the internal list could be modified:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; hash((1, &#x5B;2,3]))\nTraceback (most recent call last):\n  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;\nTypeError: unhashable type: &#039;list&#039;\n\n<\/pre><\/div>\n\n\n<p>These <a href=\"https:\/\/www.askpython.com\/python-modules\/python-collections\" data-type=\"post\" data-id=\"1412\">mutable collections<\/a> can\u2019t be hashed directly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>List<\/li>\n\n\n\n<li>Set<\/li>\n\n\n\n<li>Dictionary<\/li>\n\n\n\n<li>Bytearray<\/li>\n\n\n\n<li>User-defined classes (unless&nbsp;<strong>hash<\/strong>&nbsp;is overridden)<\/li>\n<\/ul>\n\n\n\n<p>While these <a href=\"https:\/\/www.askpython.com\/python\/oops\/immutable-objects-in-python\" data-type=\"post\" data-id=\"9736\">immutable objects<\/a> can be hashed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Integer<\/li>\n\n\n\n<li>Float<\/li>\n\n\n\n<li>String<\/li>\n\n\n\n<li>Tuple<\/li>\n\n\n\n<li>Range<\/li>\n\n\n\n<li>Frozenset<\/li>\n\n\n\n<li>Bytes<\/li>\n<\/ul>\n\n\n\n<p>When used as dictionary keys or set members, those hashable immutable objects allow for optimized hash table performance and comparisons via the hash.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"real-world-examples-of-hashable-objects\">Real-World Examples of Hashable Objects<\/h2>\n\n\n\n<p>Hashability comes up often in Python programming. Here are some common examples:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Dictionary Keys<\/strong><\/h3>\n\n\n\n<p>Dictionaries can only use hashable objects like strings or tuples as keys. This Twitter API response contains dictionaries with account IDs as keys:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n{\n    &quot;data&quot;: {\n        &quot;2244994945&quot;: {\n            &quot;id&quot;: &quot;2244994945&quot;,\n            &quot;name&quot;: &quot;Twitter Dev&quot;\n        },\n        &quot;783214&quot;: {  \n            &quot;id&quot;: &quot;783214&quot;,\n            &quot;name&quot;: &quot;Twitter API&quot;\n        } \n    }\n}\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>Caching<\/strong><\/h3>\n\n\n\n<p>Implementations of memoization or caching decorators frequently leverage hashability to cache return values by input parameters. For example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\ncache = {}\n\ndef expensive_func(arg1, arg2):\n    key = (arg1, arg2)\n    if key not in cache:\n        cache&#x5B;key] = # expensive computation\n    return cache&#x5B;key]\n\n<\/pre><\/div>\n\n\n<p>Here&nbsp;<code>arg1<\/code>&nbsp;and&nbsp;<code>arg2<\/code>&nbsp;must be hashable so they can be used in the tuple key for cache lookups.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Data Science<\/strong><\/h3>\n\n\n\n<p>When analyzing datasets, we often want to quickly identify or count unique values, which relies on those values being hashable. For example, extracting unique categories from this e-commerce data:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\norders = &#x5B;\n    {&quot;category&quot;: &quot;Electronics&quot;, &quot;revenue&quot;: 100},\n    {&quot;category&quot;: &quot;Software&quot;, &quot;revenue&quot;: 150},\n    {&quot;category&quot;: &quot;Electronics&quot;, &quot;revenue&quot;: 200} \n]\n    \nunique_categories = set(order&#x5B;&quot;category&quot;] for order in orders)\n# {&#039;Software&#039;, &#039;Electronics&#039;}\n\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"summary\">Summary<\/h2>\n\n\n\n<p>When we talk about &#8220;hashable&#8221; objects in Python, we mean objects that have an unchanging identifier value associated with them &#8211; a hash value. This hash code is like a fingerprint that uniquely identifies a particular object.<\/p>\n\n\n\n<p>Now, why does this matter? Because having this steady, reliable hash value is the key to making Python dictionaries and sets work their magic! Behind the scenes, these data structures store and quickly look up objects using the hash as an index. Hopefully, you have a better grasp on the concept of hashability! <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Python, the term \u201chashable\u201d refers to any object with a hash value that never changes during its lifetime. This hash value allows hashable objects to be used as dictionary keys or as members of sets, providing fast lookup and comparison operations. But what exactly does it mean for an object to be hashable, and [&hellip;]<\/p>\n","protected":false},"author":77,"featured_media":64051,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-58623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python-modules"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/58623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/users\/77"}],"replies":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/comments?post=58623"}],"version-history":[{"count":0,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/58623\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media\/64051"}],"wp:attachment":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media?parent=58623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/categories?post=58623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/tags?post=58623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}