Bien que cette question n'ait aucune utilité réelle dans la pratique, je suis curieux de savoir comment Python fait l'internement de chaînes. J'ai remarqué ce qui suit.
>> "string" is "string"
>> True
C'est comme je m'y attendais.
Vous pouvez également le faire.
>> "strin"+"g" is "string"
>> True
Et c'est assez intelligent!
Mais tu ne peux pas faire ça.
>> s1 = "strin"
>> s2 = "string"
>> s1+"g" is s2
>> False
Pourquoi ne pas Python évaluer s1+"g"
, et réalisez que c'est la même chose que s1
et le pointer vers la même adresse? Que se passe-t-il réellement dans ce dernier bloc pour qu'il renvoie False
?
Ceci est spécifique à l'implémentation, mais votre interprète est probablement en train d'interner des constantes au moment de la compilation mais pas les résultats d'expressions au moment de l'exécution.
Dans ce qui suit, j'utilise CPython 2.7.3.
Dans le deuxième exemple, l'expression "strin"+"g"
Est évaluée au moment de la compilation et est remplacée par "string"
. Cela fait que les deux premiers exemples se comportent de la même manière.
Si nous examinons les bytecodes, nous verrons qu'ils sont exactement les mêmes:
# s1 = "string"
2 0 LOAD_CONST 1 ('string')
3 STORE_FAST 0 (s1)
# s2 = "strin" + "g"
3 6 LOAD_CONST 4 ('string')
9 STORE_FAST 1 (s2)
Le troisième exemple implique une concaténation d'exécution, dont le résultat n'est pas automatiquement interné:
# s3a = "strin"
# s3 = s3a + "g"
4 12 LOAD_CONST 2 ('strin')
15 STORE_FAST 2 (s3a)
5 18 LOAD_FAST 2 (s3a)
21 LOAD_CONST 3 ('g')
24 BINARY_ADD
25 STORE_FAST 3 (s3)
28 LOAD_CONST 0 (None)
31 RETURN_VALUE
Si vous deviez manuellement intern()
le résultat de la troisième expression, vous obtiendriez le même objet qu'auparavant:
>>> s3a = "strin"
>>> s3 = s3a + "g"
>>> s3 is "string"
False
>>> intern(s3) is "string"
True
Cas 1
>>> x = "123"
>>> y = "123"
>>> x == y
True
>>> x is y
True
>>> id(x)
50986112
>>> id(y)
50986112
Cas 2
>>> x = "12"
>>> y = "123"
>>> x = x + "3"
>>> x is y
False
>>> x == y
True
Maintenant, votre question est de savoir pourquoi l'id est le même dans le cas 1 et pas dans le cas 2.
Dans le cas 1, vous avez affecté une chaîne littérale "123"
à x
et y
.
Étant donné que la chaîne est immuable, il est logique que l'interpréteur ne stocke la chaîne littérale qu'une seule fois et pointe toutes les variables vers le même objet.
Par conséquent, vous voyez l'identifiant comme identique.
Dans le cas 2, vous modifiez x
en utilisant la concaténation. x
et y
ont les mêmes valeurs, mais pas la même identité.
Les deux pointent vers des objets différents en mémoire. Ils ont donc des opérateurs id
et is
différents renvoyés False