web-dev-qa-db-fra.com

Pourquoi les entiers sont-ils immuables en Python?

Je comprends les différences entre les objets mutables et immuables en Python. J'ai lu de nombreux articles sur les différences. Cependant, je n'ai rien lu concernant POURQUOI les entiers sont des objets immuables.

Existe-t-il une raison à cela? Ou est-ce que la réponse "c'est comme ça"?

Edit: je suis invité à "différencier" cette question des autres questions car il semble que ce soit une question posée précédemment. Cependant, je crois que ce que je demande est plus une question philosophique Python plutôt qu'une question technique Python.

Il semble que les objets 'primitifs' dans Python (c'est-à-dire les chaînes, les booléens, les nombres, etc.) sont immuables. J'ai également remarqué que les types de données dérivés qui sont constitués de primitives (c'est-à-dire les dict , listes, classes) sont mutables.

Est-ce là où la ligne est tracée, qu'un objet soit ou non modifiable? Primitif vs dérivé?

20
Izzo

Rendre les entiers mutables serait très contre-intuitif à la façon dont nous sommes habitués à travailler avec eux.

Considérez ce fragment de code:

a = 1       # assign 1 to a
b = a+2     # assign 3 to b, leave a at 1

Une fois ces affectations exécutées, nous nous attendons à ce que a ait la valeur 1 et b ait la valeur 3. L'opération d'addition crée une nouvelle valeur entière à partir de l'entier stocké dans - a et une instance de l'entier 2. Si l'opération d'addition a simplement pris l'entier à a et l'a simplement muté, alors les deux a et b aurait la valeur 3.

Nous nous attendons donc à ce que les opérations arithmétiques créent de nouvelles valeurs pour leurs résultats - et ne modifient pas leurs paramètres d'entrée.

Cependant, il existe des cas où la mutation d'une structure de données est plus pratique et plus efficace. Supposons pour le moment que list.append(x) n'a pas modifié list mais a renvoyé une nouvelle copie de list avec x en annexe. Ensuite, une fonction comme celle-ci:

def foo():
  nums = []
  for x in range(0,10):
    nums.append(x)
  return nums

retournerait simplement la liste vide. (N'oubliez pas - ici nums.append(x) ne modifie pas nums - il renvoie une nouvelle liste avec x ajouté. Mais cette nouvelle liste n'est enregistrée nulle part.)

Il faudrait écrire la routine foo comme ceci:

def foo():
  nums = []
  for x in range(0,10):
    nums = nums.append(x)
  return nums

(Ceci, en fait, est très similaire à la situation avec Python chaînes jusqu'à environ 2,6 ou peut-être 2,5.)

De plus, chaque fois que nous affectons nums = nums.append(x), nous copions une liste dont la taille augmente, ce qui entraîne un comportement quadratique. Pour ces raisons, nous faisons des listes mutables objets.

Une conséquence de rendre les listes mutables est qu'après ces déclarations:

a = [1,2,3]
b = a
a.append(4)

la liste b est devenue [1,2,3,4]. C'est quelque chose avec lequel nous vivons même si cela nous fait encore de temps en temps monter.

16
ErikR

Quelles sont les décisions de conception pour rendre les nombres immuables en Python?

Il y a plusieurs raisons à l'immuabilité, voyons d'abord quelles sont les raisons de l'immuabilité?

1- Mémoire

  • Économise de la mémoire. S'il est bien connu qu'un objet est immuable, il peut être facilement copié en créant une nouvelle référence au même objet.
  • Performance. Python peut allouer de l'espace pour un objet immuable au moment de la création, et les exigences de stockage sont fixes et immuables.

2- Exécution rapide.

  • Il n'a pas à copier chaque partie de l'objet, seulement une simple référence.
  • Facile à comparer, la comparaison de l'égalité par référence est plus rapide que la comparaison des valeurs.

3- Sécurité:

  • Dans les applications multithread Différents threads peuvent interagir avec les données contenues à l'intérieur des objets immuables, sans se soucier de la cohérence des données.
  • L'état interne de votre programme sera cohérent même si vous avez des exceptions.
  • Les classes doivent être immuables à moins qu'il n'y ait une très bonne raison de les rendre mutables ...

4- Facilité d'utilisation

  • Est plus facile à lire, plus facile à entretenir et moins susceptible d'échouer de manière étrange et imprévisible.
  • Les objets immuables sont plus faciles à tester, en raison non seulement de leur facilité de simulation, mais également des modèles de code qu'ils ont tendance à appliquer.

5- Les clés doivent être immuables. Ce qui signifie que vous pouvez utiliser des chaînes, des nombres ou des tuples comme clé de dictionnaire. C'est quelque chose que vous souhaitez utiliser.

The hash table implementation of dictionaries uses a hash value calculated from the key value to find the key. If the key were a mutable object, its value could change, and thus its hash could also change. But since whoever changes the key object can’t tell that it was being used as a dictionary key, it can’t move the entry around in the dictionary. Then, when you try to look up the same object in the dictionary it won’t be found because its hash value is different. If you tried to look up the old value it wouldn’t be found either, because the value of the object found in that hash bin would be different.

Revenons aux nombres entiers:

  • Sécurité ( 3 ), facile à utiliser ( 4 ) et capacité de l'utilisation de nombres comme clés dans les dictionnaires ( 5 ) est la raison pour laquelle il a été décidé de rendre les nombres immuables.

  • A des exigences de mémoire fixes depuis la création ( 1 ).

  • Tout en Python est un objet, les nombres (comme les chaînes) sont des objets "élémentaires". Aucune quantité d'activité changera la valeur 8 en n'importe quoi d'autre, et aucune quantité d'activité ne changera la chaîne "huit" en autre chose. C'est parce que décision dans la conception aussi.

6
Facundo Victor