Maison  >  Article  >  développement back-end  >  Pourquoi l'opérateur \'is\' se comporte-t-il différemment avec des entiers non mis en cache à l'intérieur et à l'extérieur d'une fonction en Python ?

Pourquoi l'opérateur \'is\' se comporte-t-il différemment avec des entiers non mis en cache à l'intérieur et à l'extérieur d'une fonction en Python ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-31 19:22:02257parcourir

Why does the 'is' operator behave differently with non-cached integers inside and outside a function in Python?

Comportement inattendu de l'opérateur 'is' avec des entiers non mis en cache

Enquête

Lors de l'expérimentation avec l'interpréteur de Python, un paradoxe a été remarqué concernant le ' est l'opérateur. Plus précisément, « is » renvoie True lorsqu'il est évalué dans une fonction mais False lorsqu'il est évalué en dehors de celle-ci :

>>> def func():
...     a = 1000
...     b = 1000
...     return a is b
...

>>> a = 1000
>>> b = 1000
>>> a is b, func()
(False, True)

Puisque « is » évalue l'« id » de l'objet, cela implique que dans la fonction « func », 'a' et 'b' font référence à la même instance int. Cependant, en dehors de la fonction, ils font référence à des objets différents. Pourquoi est-ce le cas ?

Explication

Le manuel de référence Python offre une clarification perspicace :

"Un bloc est un morceau de texte de programme Python qui est exécuté comme une unité . Chaque commande saisie de manière interactive est un bloc."

Au sein d'une fonction, il existe un seul bloc de code, contenant un seul objet pour le nombre 1000. Ainsi, 'id(a)' et 'id(b)'. renvoie la même valeur, ce qui donne une évaluation True.

En dehors de la fonction, nous avons deux objets de code distincts, chacun avec son objet pour 1000. Par conséquent, 'id(a)' et 'id(b) 'sont différents, conduisant à une évaluation fausse.

Cette bizarrerie n'est pas exclusive aux nombres entiers. Des résultats similaires sont observés avec, par exemple, les littéraux float. N'oubliez pas que comparer des objets pour déterminer leur identité (en utilisant « est ») est généralement déconseillé ; à la place, l'opérateur d'égalité ('==') doit être utilisé.

Démonstration de code

Pour mieux comprendre, nous pouvons approfondir les objets de code pour les deux cas :

Dans la fonction 'func' :

>>> print(dis.code_info(func))
...
Constants:
   0: None
   1: 1000

Nous avons une seule instance 'int' pour 1000 qui est attribuée à la fois à 'a' et 'b'.

En dehors de la fonction 'func' :

>>> com1 = compile("a=1000", filename="", mode="single")
>>> com2 = compile("b=1000", filename="", mode="single")
>>> id(com1.co_consts[0]) == id(com2.co_consts[0])
False

Nous voyons que chaque objet de code a son instance de 1000, conduisant à l'évaluation False.

Notes

  • Cette observation concerne CPython, l'implémentation Python la plus largement utilisée.
  • Les instructions chaînées sont évaluées à True pour « est » car elles sont traitées comme un seul bloc de code.
  • L'exécution au niveau du module donne également True.
  • Les contrôles d'identité utilisant « est » ne sont pas recommandés pour les objets mutables, car ils seront toujours évalués à False.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn