[Python] Pourquoi les ID des objets référencés sont les mêmes lorsque le même entier est affecté à différentes variables

C'est une question que j'ai rencontrée en apprenant le comportement des affectations Python.

Si vous affectez le même entier à différentes variables, l'ID de l'objet référencé sera le même. Pourquoi?

Lorsque 10 est affecté aux variables a et b comme indiqué ci-dessous,

Python


>>> a = 10
>>> b = 10

Dans mon esprit, comme ceci ↓ "** les valeurs sont toutes les deux 10, mais deux objets sont créés dans la mémoire, chacun avec des noms a et b. ID (adresse mémoire) est bien sûr différent. C'était une image de "** pointant vers **". Cela s'appelle l'affectation Python est binding / bind. スクリーンショット 2020-01-18 1.49.53.png

Cependant, lorsque je vérifie l'ID de l'objet référencé par les variables a et b,

Python


>>> id(a)
4343178640
>>> id(b)
4343178640
>>>
>>> a is b
True
>>>

#le même...!?!?!?

Il montrait exactement le même identifiant. Comme indiqué ci-dessous, ** a et b font tous deux référence au même objet **. スクリーンショット 2020-01-18 2.21.00.png Si j'avais mis b = a, j'étais satisfait de ce résultat, mais je n'ai pas substitué a à b.

D'après la documentation officielle, un objet entier entre -5 et 256 existe déjà en mémoire avant l'affectation.

J'ai cherché "python variable int id same" et cela ne s'est pas produit, alors j'ai cherché "python int same address" sur Google US et cela a été résolu.

Python WAT!? Integer Cache → [Integer Objects (document officiel)](https://docs.python.org/3/c- api / long.html # c.PyLong_FromLong)

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object. L'implémentation actuelle tente de conserver un tableau d'objets entiers pour tous les entiers de -5 à 256, et la génération d'un nombre dans cette plage renvoie en fait une référence à un objet existant. ..

Donc c'est pourquoi

"Les entiers de -5 à 256 sont prêts à être utilisés en mémoire. Ainsi, lorsque l'affectation de ʻa = 10`` b = 10` est effectuée, les deux variables a et b sont déjà en mémoire. Reportez-vous simplement à l'objet entier «10» ci-dessus, et le résultat sera le même ID. "

Si vous essayez avec des valeurs de 256, 257, qui est la limite entre les extensions et non en mémoire,

Python


>>> a = 256
>>> b = 256
>>> id(a)
4343186512
>>> id(b)
4343186512 #L'ID est le même
>>> a is b
True
>>>
>>> a = 257
>>> b = 257
>>> id(a)
4346386992
>>> id(b)
4346387088 #L'ID est différent! !!
>>> a is b
False
>>>

Comme prévu dans la documentation officielle, nous pouvons voir à partir de 257 que les objets référencés par la variable a et la variable b sont différents.

Si vous lisez le site ci-dessous, le but est "d'utiliser fréquemment les numéros de -5 à 256 et de les rendre immédiatement disponibles pour les performances". Real Python: Small Integer Caching

Expérimentez avec des nombres à virgule flottante au lieu d'entiers

Il disait "J'essaye de garder un tableau de ** objets entiers ** ~", donc je l'ai essayé avec des nombres à virgule flottante ...

Python


>>> a = 0.5
>>> b = 0.5
>>> id(a)
4317942456
>>> id(b)
4317941880 #L'ID est différent
>>> a is b
False
>>>

Le résultat est que les valeurs elles-mêmes sont les mêmes, mais les ID sont différents pour les nombres à virgule flottante. J'ai pu confirmer qu'il ne s'agit également que de nombres entiers comme documenté.

Environnement éprouvé

Python 3.7.1

Recommended Posts

[Python] Pourquoi les ID des objets référencés sont les mêmes lorsque le même entier est affecté à différentes variables
Que faire lorsque le type de valeur est ambigu en Python?
Quand Selenium dit que la version du pilote Chrome est différente (Python)
python Comment notifier automatiquement par téléphone lorsque le système tombe en panne
Le nombre est-il équivalent à un entier?
La réponse de "1/2" est différente entre python2 et 3
Pourquoi Python doit-il écrire un deux-points?
Le moment auquel la valeur de l'argument par défaut est évaluée diffère entre Ruby et Python.
[Introduction à Python] Quel est l'important "if __name__ == '__ main__':" lorsqu'il s'agit de modules?