Sont mis en commun des chaînes en Python
-
22-09-2019 - |
Question
Est-ce que Python a une piscine de toutes les chaînes et sont-ils (cordes) singletons là-bas?
Plus précisément, dans le code suivant une ou deux chaînes ont été créées en mémoire:
a = str(num)
b = str(num)
La solution
Les chaînes sont immuables en Python, de sorte que la mise en œuvre peut décider de stagiaire (c'est un terme souvent associé à C #, ce qui signifie que certaines chaînes sont stockées dans une piscine) chaînes ou non.
Dans votre exemple, vous créez dynamiquement des chaînes. CPython fait pas toujours regarder dans la piscine pour détecter si la chaîne est déjà là - il n'a pas de sens parce que vous aussi devez d'abord réserver la mémoire pour créer la chaîne, puis le comparer à le contenu de la piscine (inefficace pour les longues chaînes).
Mais pour les chaînes de longueur 1, CPython ne regarde dans la piscine (cf. "stringobject.c"):
static PyStringObject *characters[UCHAR_MAX + 1];
...
PyObject *
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
{
...
if (size == 1 && str != NULL &&
(op = characters[*str & UCHAR_MAX]) != NULL)
{
#ifdef COUNT_ALLOCS
one_strings++;
#endif
Py_INCREF(op);
return (PyObject *)op;
}
...
a = str(num)
b = str(num)
print a is b # <-- this will print False in most cases (but try str(1) is str(1))
Mais lorsque vous utilisez constante chaînes directement dans votre code, CPython utilise la même instance de chaîne:
a = "text"
b = "text"
print a is b # <-- this will print True
Autres conseils
En général, les chaînes ne sont pas internées en Python, mais ils ne semblent parfois être:
>>> str(5) is str(5)
True
>>> str(50) is str(50)
False
Ce n'est pas rare en Python, où des objets communs peuvent être optimisés de manière à les inhabituelles ne sont pas:
>>> int(5+0) is int(5+0)
True
>>> int(50+0) is int(50+0)
True
>>> int(500+0) is int(500+0)
False
Et gardez à l'esprit, toutes ces sortes de détails différeront entre les implémentations de Python, et même entre les versions de la même application.
Les chaînes ne sont pas internées en général. Dans votre exemple, deux chaînes seront créées (à l'exception des valeurs comprises entre 0 et 9). Pour tester cela, nous pouvons utiliser l'opérateur is
pour voir si les deux chaînes sont le même objet:
>>> str(1056) is str(1056)
False
la constante de piscine en python distinguer piscine petit entier et un grand pool de nombre entier, et la piscine petit entier est la gamme de [-5, 257); et d'autres nombres entiers dans la grande piscine entière. En Cython, si définit une liste chaînée pour stocker ces données, où chercher les données devient très pratique et rapide.
# ifndef NSMALLPOSINTS
# define NSMALLPOSINTS 257
# endif
# ifndef NSMALLNEGINTS
# define NSMALLNEGINTS 5
# endif
# if NSMALLPOSINTS + NSMALLNEGINTS > 0
static PyIntObject * small_ints[NSMALLPOSINTS + NSMALLNEGINTS];
# endif
BTW: le nombre entier 257 peut-être étranger; si deux objets qu'ils ont les mêmes valeurs sont dans le même domaine, leur adresse peut être ou ne pas être le même, cela dépend du contexte du processus; alors que, si elles sont dans les différents domaines, leurs adresses doivent être différence
et par ailleurs, selon le type de chaîne, cython fournissent également une piscine constante que la longueur de chaîne doit être un, alors il peut être pas le même objet
a = str(11)
b = str(11)
print a == b # True
print a is b # False
c = str("A")
d = str("A")
print c == d # True
print c is d # True
aa = 12
bb = 12
print aa == bb # True
print aa is bb # True
cc = 333
dd = 333
print cc == dd # True
print cc is dd # False
comparer leurs adresses, est d'obtenir de manière transparente les solutions à venir