Python passe par des références [dupliquer]
cette question a déjà une réponse ici:
- " is " l'opérateur se comporte de façon inattendue avec des entiers 11 réponses
Bonjour, je suis en train d'essayer de comprendre comment Python passer par des ouvrages de référence. J'ai un exemple:
>>>a = 1
>>>b = 1
>>>id(a);id(b)
140522779858088
140522779858088
C'est parfaitement logique puisque a et b sont tous deux référence à la même valeur qu'il aurait l'identité. Ce que je ne comprends pas tout à fait, c'est comment cet exemple:
>>>a = 4.4
>>>b = 1.0+3.4
>>>id(a);id(b)
140522778796184
140522778796136
est différent de cet exemple:
>>>a = 2
>>>b = 2 + 0
>>>id(a);id(b)
140522779858064
140522779858064
est-ce parce que dans le troisième exemple l'objet 0 int est considéré comme "Aucun" par l'interpréteur et n'est pas reconnu comme ayant besoin d'une identité différente de l'objet quelle variable "a" renvoie(2)? Alors que dans le deuxième exemple "b" est ajouter deux objets int différents et l'interpréteur alloue de la mémoire pour les deux objets à ajouter, ce qui donne la variable "a", une identité différente de la variable "b"?
3 réponses
dans votre premier exemple, les noms a
et b
renvoient tous deux au même objet à cause de interning . L'instruction assignée a produit un entier avec le même id
seulement parce qu'il a réutilisé un objet préexistant qui s'est avéré traîner dans la mémoire déjà. Ce n'est pas un comportement fiable des entiers:
>>> a = 257
>>> b = 257
>>> id(a), id(b)
(30610608, 30610728)
comme démontré ci-dessus, si vous choisissez un entier assez grand alors il se comporteront comme les flotteurs de votre deuxième exemple se sont comportés. Et interner de petits entiers est optionnel dans le langage Python de toute façon, il se trouve que c'est un détail d'implémentation du CPython: c'est une optimisation de performance destinée à éviter la surcharge de créer un nouvel objet. Nous pouvons accélérer les choses en cachant les instances entières couramment utilisées, au prix d'une empreinte mémoire plus élevée de L'interpréteur Python.
ne pensez pas à "référence" et "value" en traitant avec Python, le modèle qui fonctionne pour C ne fonctionne pas vraiment bien ici. Pensez plutôt aux" noms "et aux"objets".
le diagramme ci-dessus illustre votre troisième exemple. 2
est un objet, a
et b
sont des noms. Nous pouvons avoir différents noms pointant vers le même objet. Et les objets peuvent exister sans nom.
Affectation une variable uniquement attache une étiquette . Et supprimer une variable seulement supprime un nametag . Si vous gardez cette idée à l'esprit, alors le modèle d'objet Python ne vous surprendra plus jamais.
Comme l'a déclaré ici , Disponible caches entiers allant de -5 à 256. Donc toutes les variables dans cette plage avec la même valeur partagent le même id (Je ne parierais pas là-dessus pour les versions futures, mais c'est l'implémentation actuelle)
il n'y a pas de telle chose pour les flotteurs probablement parce qu'il y a une "infinité" de valeurs possibles (bien pas infinie mais grande à cause de la virgule flottante), donc la chance de calculer la même valeur par des moyens différents est vraiment bas par rapport aux entiers.
>>> a=4.0
>>> b=4.0
>>> a is b
False
les variables Python sont toujours des références à des objets. Ces objets peuvent être divisés en objets mutables et immuables.
un type mutable peut être modifié sans que son id soit modifié, ainsi chaque variable qui pointe vers cet objet sera mise à jour. Cependant, un objet immuable ne peut pas être modifié de cette façon, donc Python génère un nouvel objet avec les modifications et réassigne la variable à pointer vers ce nouvel objet, donc l'id de la variable avant la modification. ne sera pas correspondre à l'id de la variable après le changement.
les entiers et les flotteurs sont immuables, donc après un changement, ils pointent vers un objet différent et ont donc des identifiants différents.
le problème est que CPython "cache" certaines valeurs entières communes de sorte qu'il n'y a pas plusieurs objets avec la même valeur afin de sauver la mémoire, et 2 est l'un de ces entiers cache-ed, de sorte que chaque fois qu'une variable pointe sur l'entier 2 il aura le même id (son la valeur sera différente pour différentes exécutions python).