{"id":3483,"date":"2025-04-22T14:28:27","date_gmt":"2025-04-22T12:28:27","guid":{"rendered":"https:\/\/blog.nanuq.me\/?p=3483"},"modified":"2025-04-22T14:28:27","modified_gmt":"2025-04-22T12:28:27","slug":"python3-mutable-immutable-tout-est-objet","status":"publish","type":"post","link":"https:\/\/blog.nanuq.me\/?p=3483","title":{"rendered":"Python3 : Mutable, Immutable&#8230; tout est objet !"},"content":{"rendered":"<p>Du Python, des objets, des identifiants, et des petites subtilit\u00e9s&#8230;<!--more--><\/p>\n<h2>Disclaimer<\/h2>\n<p>Cet article a \u00e9t\u00e9 initialement <a href=\"https:\/\/medium.com\/@regniersimon\/python3-mutable-immutable-everything-is-object-e7ac0149dd1b\">\u00e9crit en anglais<\/a> (conform\u00e9ment \u00e0 la consigne) mais le blog \u00e9tant en francais, je me suis permis de le traduire ci dessous :<\/p>\n<h2>Introduction<\/h2>\n<p dir=\"auto\">Dans le cadre de ma reconversion en informatique, je dois apprendre \u00e0 coder, mais aussi \u00e0 communiquer avec d\u2019autres personnes et, en particulier, \u00e0 r\u00e9diger de la documentation technique. Dans cette optique, nous devons r\u00e9diger un article de vulgarisation au sujet de la programmation orient\u00e9e objet et de Python. En effet, en Python, tout est objet et il est important de comprendre certains principes\u2026<\/p>\n<hr>\n<h2>ID et Type<\/h2>\n<p dir=\"auto\">Un petit rappel n\u00e9anmoins : pour bien comprendre ce qui va suivre, il faut bien comprendre ce qu&rsquo;est un objet. Un objet est une entit\u00e9 en m\u00e9moire qui contient des donn\u00e9es. Chaque objet a :<\/p>\n<ul>\n<li>un <strong>type<\/strong> : c&rsquo;est-\u00e0-dire sa classe d&rsquo;origine (<code class=\"\">int<\/code>, <code class=\"\">str<\/code>, <code class=\"\">list<\/code>, <code class=\"\">MyCustomObject<\/code>, etc.)<\/li>\n<li>un <strong>identifiant<\/strong> : Un identifiant unique qui est associ\u00e9 \u00e0 l&rsquo;adresse m\u00e9moire utilis\u00e9e. Que nous appellerons <code class=\"\">id<\/code> par la suite.<\/li>\n<li>une <strong>valeur<\/strong> : la donn\u00e9e associ\u00e9e.<\/li>\n<\/ul>\n<p dir=\"auto\">En Python, il faut savoir que tout est un objet. Les <code class=\"\">int<\/code>, <code class=\"\">str<\/code>, <code class=\"\">list<\/code>, mais aussi les fonctions, les classes, etc&#8230;<\/p>\n<p dir=\"auto\">Par cons\u00e9quent, pour chaque objet, on peut savoir son <code class=\"\">id<\/code> ainsi que son <code class=\"\">type<\/code> avec les commandes <code class=\"\">id<\/code> et <code class=\"\">type<\/code>.<\/p>\n<p dir=\"auto\"><strong>Exemple<\/strong><\/p>\n<pre>x = 1242 # D\u00e9claration d'une variable X \nprint(x)# Affichage de la valeur 1242 \nprint(id(x)) # Affichage de son identifiant\nprint(type(x)) # Affichage de son type (&lt;class 'int'&gt;)\n\ny = 10.1010 # D\u00e9claration d'une variable Y\nprint(y) # Affichage de la valeur 10.1010\nprint(id(y)) # Affichage de son identifiant\nprint(type(y)) # Affichage de son type (&lt;class 'float'&gt;)\n\nz = \"Live long and prosper\" # D\u00e9claration d'une variable Z\nprint(z) # Affichage de la valeur \"Live long and prosper\"\nprint(id(z)) # Affichage de son identifiant\nprint(type(z)) # Affichage de son type (&lt;class 'str'&gt;)<\/pre>\n<p dir=\"auto\">Pour aller plus loin, manipulons un peu le code :<\/p>\n<pre>a = 1337\nb = a\nc = 1991\nprint(\"ID of a:\", id(a))\nprint(\"ID of b:\", id(b))\nprint(\"ID of c:\", id(c))<\/pre>\n<p dir=\"auto\">Et voici un exemple d&rsquo;output du code ci-dessus :<\/p>\n<pre>ID of a: 138767925128816\nID of b: 138767925128816\nID of c: 138767925128880<\/pre>\n<p dir=\"auto\">On peut voir que l&rsquo;<code class=\"\">id<\/code> de <code class=\"\">a<\/code> et de <code class=\"\">b<\/code> sont identiques. <strong>Pourquoi ?<\/strong> Parce que tout est objet en Python et que la valeur de <code class=\"\">a<\/code> et la valeur de <code class=\"\">b<\/code> pointent vers la m\u00eame adresse m\u00e9moire. Donc ils ont le m\u00eame <code class=\"\">id<\/code> et la m\u00eame valeur. Ce qui n&rsquo;est pas le cas de <code class=\"\">c<\/code> qui poss\u00e8de une valeur diff\u00e9rente.<\/p>\n<hr>\n<h2>Objets mutables<\/h2>\n<p dir=\"auto\">En Python, certains objets sont dits <strong>mutables<\/strong>, c&rsquo;est-\u00e0-dire qu&rsquo;on peut les modifier \u00e0 loisir et cela va modifier la valeur de l&rsquo;objet, sans modifier son adresse m\u00e9moire. En Python, les principaux objets mutables sont les suivants :<\/p>\n<ul>\n<li><code class=\"\">list<\/code> Exemple : <code class=\"\">[1, 2, 3]<\/code><\/li>\n<li><code class=\"\">dict<\/code> Exemple : <code class=\"\">{\"a\": 1, \"b\": 2}<\/code><\/li>\n<li><code class=\"\">set<\/code> Exemple : <code class=\"\">{1, 2, 3}<\/code><\/li>\n<\/ul>\n<p dir=\"auto\">C&rsquo;est-\u00e0-dire que si l&rsquo;on peut, par exemple, ajouter des valeurs \u00e0 une liste, sans que cela modifie son <code class=\"\">id<\/code>, c&rsquo;est-\u00e0-dire l&rsquo;adresse m\u00e9moire qui est associ\u00e9e.<\/p>\n<p dir=\"auto\"><strong>Exemple :<\/strong><\/p>\n<pre>mylist = [1,2,3]\nprint(\"Value of mylist before update:\", mylist)\nprint(\"ID of mylist before update:\", id(mylist))\nmylist.append(4)\nprint(\"Value of mylist after update:\", mylist)\nprint(\"ID of mylist after update:\", id(mylist))<\/pre>\n<p dir=\"auto\"><strong>Output :<\/strong><\/p>\n<pre>Value of mylist before update: [1, 2, 3]\nID of mylist before update: 135825999858112\nValue of mylist after update: [1, 2, 3, 4]\nID of mylist after update: 135825999858112<\/pre>\n<p dir=\"auto\">Comme on peut le voir, <strong>m\u00eame si les valeurs dans l&rsquo;objet <code class=\"\">mylist<\/code> ont \u00e9t\u00e9 modifi\u00e9es<\/strong>, vu que c&rsquo;est un objet mutable, <strong>on garde le m\u00eame <code class=\"\">id<\/code> !<\/strong><\/p>\n<hr>\n<h2>Objets immuables<\/h2>\n<p dir=\"auto\">On a vu qu\u2019il existe des objets mutables. Par opposition, les objets immuables sont ceux qui ne peuvent pas \u00eatre modifi\u00e9s. Et les objets immuables sont tous ceux qui ne sont pas dans la liste des objets mutables que l&rsquo;on vient de voir pr\u00e9c\u00e9demment ; mais voici les principaux :<\/p>\n<ul>\n<li><code class=\"\">int<\/code> Exemple : <code class=\"\">x = 42<\/code><\/li>\n<li><code class=\"\">float<\/code> Exemple : <code class=\"\">x = 101.010<\/code><\/li>\n<li><code class=\"\">str<\/code> Exemple : <code class=\"\">x = \"hello darkness my old friend\"<\/code><\/li>\n<li><code class=\"\">bool<\/code> Exemple : <code class=\"\">x = True<\/code><\/li>\n<li><code class=\"\">tuples<\/code> Exemple : <code class=\"\">(1,2,3)<\/code><\/li>\n<\/ul>\n<p dir=\"auto\">Il en existe d&rsquo;autres moins utilis\u00e9s comme, par exemple, <code class=\"\">frozenset<\/code> ou <code class=\"\">bytes<\/code>.<\/p>\n<p dir=\"auto\"><strong>Exemple :<\/strong><\/p>\n<pre>myint = 101010\nprint(\"Value of myint before update:\", myint)\nprint(\"ID of myint before update:\", id(myint))\nmyint = myint + 1\nprint(\"Value of myint after update:\", myint)\nprint(\"ID of myint after update:\", id(myint))<\/pre>\n<p dir=\"auto\"><strong>Output :<\/strong><\/p>\n<pre>Value of myint before update: 101010\nID of myint before update: 135973928496752\nValue of myint after update: 101011\nID of myint after update: 135973928496656<\/pre>\n<p dir=\"auto\">Comme on peut le voir, vu qu&rsquo;on change la valeur de <code class=\"\">myint<\/code>, Python attribue une nouvelle valeur \u00e0 <code class=\"\">myint<\/code> et doit donc lui donner une nouvelle adresse m\u00e9moire pour stocker cette nouvelle valeur, et par cons\u00e9quent un nouvel <code class=\"\">id<\/code> ! <strong>C&rsquo;est pour cela que les <code class=\"\">id<\/code> ne sont plus les m\u00eames apr\u00e8s la modification.<\/strong><\/p>\n<hr>\n<h2>Comment les arguments sont pass\u00e9s aux fonctions<\/h2>\n<p dir=\"auto\">En Python, tout est <strong>objet<\/strong>, par cons\u00e9quent quand l&rsquo;on passe des arguments \u00e0 une fonction, c&rsquo;est en r\u00e9alit\u00e9 la r\u00e9f\u00e9rence \u00e0 cet objet qui est pass\u00e9e et non pas l&rsquo;objet lui-m\u00eame. Cela signifie que la fonction voit l&rsquo;objet original et agit directement sur lui si c&rsquo;est un objet mutable.<\/p>\n<p dir=\"auto\">C&rsquo;est-\u00e0-dire que si j&rsquo;ai une variable <code class=\"\">myvar = 12<\/code> et que je dois utiliser cette variable dans une fonction, ce que re\u00e7oit la fonction <strong>est un lien vers l&rsquo;objet 12 stock\u00e9 en m\u00e9moire.<\/strong><\/p>\n<h3>Avec des immuables<\/h3>\n<p dir=\"auto\">Les objets immuables ne peuvent pas \u00eatre modifi\u00e9s comme on l&rsquo;a vu pr\u00e9c\u00e9demment. Donc m\u00eame en passant l&rsquo;objet \u00e0 la fonction, vu que l&rsquo;argument est pass\u00e9 par r\u00e9f\u00e9rence, on ne change pas l&rsquo;objet original.<\/p>\n<p dir=\"auto\"><strong>Exemple :<\/strong><\/p>\n<pre>def increment(x):\n     x += 1\n\na = 5\nincrement(a)\nprint(a) # Affiche 5 car l'objet original n'a pas \u00e9t\u00e9 modifi\u00e9<\/pre>\n<p dir=\"auto\">Ici, <code class=\"\">x<\/code> dans la fonction re\u00e7oit la r\u00e9f\u00e9rence \u00e0 <code class=\"\">a<\/code>, mais comme les entiers sont immuables, l&rsquo;assignation <code class=\"\">x += 1<\/code> cr\u00e9e un nouvel objet. <code class=\"\">a<\/code> reste inchang\u00e9 en dehors de la fonction.<\/p>\n<h3>Avec les mutables<\/h3>\n<p dir=\"auto\">Les objets mutables peuvent \u00eatre modifi\u00e9s \u00e0 la vol\u00e9e comme on l&rsquo;a vu pr\u00e9c\u00e9demment. Donc en passant l&rsquo;objet \u00e0 la fonction, on modifie l&rsquo;objet original :<\/p>\n<p dir=\"auto\"><strong>Exemple :<\/strong><\/p>\n<pre>def modify(l):\n     l.append(3)\n\na = [1, 2]\nmodify(a)\nprint(a) # Affiche 1,2,3 car l'objet original a \u00e9t\u00e9 modifi\u00e9<\/pre>\n<p dir=\"auto\">Ici, <code class=\"\">l<\/code> dans la fonction re\u00e7oit la r\u00e9f\u00e9rence \u00e0 <code class=\"\">a<\/code>, mais comme les listes sont mutables, l&rsquo;assignation <code class=\"\">l.append(3)<\/code> modifie l&rsquo;objet <code class=\"\">a<\/code>.<\/p>\n<h3>Pour aller plus loin<\/h3>\n<p>Certaines valeurs simples comme les petits entiers (de -5 \u00e0 256) sont <strong>pr\u00e9-enregistr\u00e9es en m\u00e9moire.\u00a0<\/strong>Cela signifie que m\u00eame si on affecte une variable avec l&rsquo;une de ces valeurs, Python r\u00e9utilise la m\u00eame adresse m\u00e9moire. Cette optimisation est appel\u00e9e <em>interning<\/em>.<br>\n<strong>Par exemple :<\/strong><\/p>\n<pre>print(\"Exemple with int in range -5 \/ 255 (intering) \")\nx1 = 42\ny1 = x1 + 0\nprint(\"ID of x:\", id(x1))\nprint(\"ID of y:\", id(y1))\nprint(\"Exemple with int &gt; 256\")\nx2 = 9999\ny2 = x2 + 0\nprint(\"ID of x:\", id(x2))\nprint(\"ID of y:\", id(y2))\n\n<\/pre>\n<p dir=\"auto\"><strong>Output:<\/strong><\/p>\n<pre dir=\"auto\">Exemple with int in range -5 \/ 255 (intering) \nID of x: 133548043464040\nID of y: 133548043464040\nExemple with int &gt; 256\nID of x: 133548031831600\nID of y: 133548031831568<\/pre>\n<p dir=\"auto\">M\u00eame si on d\u00e9clare deux variables diff\u00e9rentes, elles pointent vers le m\u00eame objet en m\u00e9moire, car Python a d\u00e9cid\u00e9 de ne pas en recr\u00e9er un car c&rsquo;est une valeur courante (entre -5 et 255).<\/p>\n<p dir=\"auto\">Voila, c&rsquo;est tout pour le moment !<\/p>\n<p dir=\"auto\">\n","protected":false},"excerpt":{"rendered":"<p>Du Python, des objets, des identifiants, et des petites subtilit\u00e9s&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3484,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[13,90,95,98],"_links":{"self":[{"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/wp\/v2\/posts\/3483"}],"collection":[{"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3483"}],"version-history":[{"count":0,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/wp\/v2\/posts\/3483\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=\/"}],"wp:attachment":[{"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nanuq.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}