2009-11-03 6 views
4

Est-ce que les sous-chaînes python créer une chaîne entièrement nouvelle (la copie du contenu) lorsque vous effectuez une opération de sous-chaîne comme:chaîne Python interner et

new_string = my_old_string[foo:bar] 

Ou faut-il utiliser interner pour pointer vers les anciennes données? Par souci de clarification, je suis curieux de savoir si le tampon de caractères sous-jacent est partagé tel quel en Java. Je me rends compte que les chaînes sont immuables et apparaîtront toujours comme une chaîne complètement nouvelle, et il faudrait que ce soit un objet chaîne entièrement nouveau.

Répondre

8

examen the source révèle:

Lorsque les index de tranche correspondent au début et à la fin de la chaîne d'origine, la chaîne d'origine est retourné.

Sinon, vous obtenez le résultat de la fonction PyString_FromStringAndSize, qui prend l'objet chaîne existant. Cette fonction renvoie une chaîne internée dans le cas d'une chaîne de 0 ou de 1 caractère; sinon, il copie la sous-chaîne dans un nouvel objet chaîne.

-2

En Python, les chaînes sont immuables. Cela signifie que vous obtiendrez toujours une copie sur n'importe quelle tranche, concaténer ou d'autres opérations.

http://effbot.org/pyfaq/why-are-python-strings-immutable.htm est une bonne explication pour certaines des raisons derrière les chaînes immuables.

+0

En Java, les chaînes sont immuables, mais la méthode substring renvoie une référence au même tampon de caractères. –

+0

Excellente clarification pour ma question Jonathan. – rhettg

2

C'est une toute nouvelle corde (de sorte que la vieille plus grande peut être lâchée si possible, plutôt que de rester en vie juste parce qu'une petite ficelle a été tranchée et gardée).

intern est une chose différente, cependant.

0

On dirait que je peux répondre à ma propre question, a ouvert la source et devinez ce que je trouve:

static PyObject * 
    string_slice(register PyStringObject *a, register Py_ssize_t i, 
     register Py_ssize_t j) 

    ... snip ... 

    return PyString_FromStringAndSize(a->ob_sval + i, j-i); 

..et aucune référence à interner. FromStringAndSize() uniquement explicitement interns sur les chaînes de taille 1 et 0 Il semble donc évident que vous aurez toujours un objet totalement nouveau et qu'ils ne partageront aucun tampon.

+0

Vous regardez la mauvaise fonction; vous voulez 'string_slice'. –

+0

Tout à fait raison ... je viens de passer une heure à essayer de comprendre pourquoi le test ne fonctionnait pas ce code. – rhettg

8

Vous pourriez également être intéressé par iSlice qui fournit une vue de la chaîne d'origine

>>> from sys import getrefcount 
>>> from itertools import islice 
>>> h="foobarbaz" 
>>> getrefcount(h) 
2 
>>> g=islice(h,3,6) 
>>> getrefcount(h) 
3 
>>> "".join(g) 
'bar' 
>>>