"en lieu" de la chaîne de modifications en Python
En Python, les chaînes sont immuables.
Quelle est la norme de l'idiome de marcher à travers une chaîne de caractère par caractère et de le modifier?
Les seules méthodes que je peux penser sont parfois vraiment stanky hacks liés à l'adhésion à l'encontre d'une chaîne de résultat.
--
Dans C:
for(int i = 0; i < strlen(s); i++)
{
s[i] = F(s[i]);
}
C'est super expressif et dit exactement ce que je suis en train de faire. C'est ce que je suis à la recherche d'.
- Je suppose que depuis qu'ils sont immuables vous ne pouvez pas "modifier"... entendez-vous construire une nouvelle chaîne de caractères char par char?
- C'est vraiment rare. Pouvez-vous donner à un contexte ou à un cas d'utilisation pour le faire?
- Ajout de bruit à un message pour les tests.
- Nathan: "Ajout de bruit à un message"? Comme dans "remplacer des caractères au hasard"? Quel est le problème avec
replace
pour cela? - Remplacer les sélectionne en fonction des éléments connus dans la liste `mystring.replace("1", "i")"; que je veux pour itérer par index - je ne sais pas quels sont les éléments qui seront dans la liste en soi. (Pourquoi a-t-il à une telle douleur?)
- Nathan: D'Accord. Vous êtes en faisant des substitutions en position. Ce n'est pas clair, parce que le code en C d'origine n'est pas claire. En C il ya tellement de nombreuses limites et les imperfections qu'il est difficile de dire ce qui est essentiel et ce qui est juste C du décalage dans l'exemple de code. "Pourquoi a-t-il à une telle douleur?"? Quoi? Pourquoi est-ce qu'être une douleur? Je ne comprends pas cette partie de votre commentaire.
Vous devez vous connecter pour publier un commentaire.
Le Python analogique de votre C:
serait:
qui est aussi très expressive. Il dit exactement ce qui se passe, mais dans un style fonctionnel plutôt que d'un style procédural.
map()
la même que la compréhension de liste et de les rejoindre?Ne pas utiliser une chaîne de caractères, utilisez quelque chose mutable comme bytearray:
Résultats dans:
Edit:
Puisque c'est un
bytearray
, vous ne le sont pas (nécessairement) de travail avec caractères. Vous travaillez avec octets. Donc cela marche aussi:donne:
Si vous souhaitez modifier les caractères dans une chaîne Unicode, vous auriez peut-être envie de travailler avec
memoryview
, mais qui ne prend pas en charge Unicode directement.vous pouvez utiliser le UserString module:
Je dirais que la plupart des Pythonic façon est d'utiliser des
map()
:C'est l'équivalent de l'écriture:
s = "".join(map(func, s))
string.translate
est probablement le plus proche de la fonction de ce que vous êtes après.str
objets ont latranslate
méthode. Il est généralement pratique à utilisermaketrans
de lastring
module siChaînes sont itérable et peut être parcouru comme des listes. Les chaînes ont également un certain nombre de méthodes de base tels que
.replace()
que peut-être ce que vous cherchez. Toutes les méthodes string retourne une nouvelle chaîne. Donc, au lieu de modifier la chaîne en place, vous pouvez simplement remplacer sa valeur.myStr[0:3][:] = 'new'
".replace("g","r")Attribution d'un caractère particulier à un indice donné dans une chaîne de caractères n'est pas une opération particulièrement courante, donc si vous vous trouvez avoir besoin de le faire, réfléchir pour savoir si il peut y avoir une meilleure façon d'accomplir la tâche. Mais si vous avez besoin de vous, probablement le plus façon standard serait de convertir la chaîne en une liste, effectuez vos modifications, puis de le convertir en une chaîne de caractères.
EDIT: posté dans bstpierre réponse,
bytearray
est probablement encore mieux pour cette tâche quelist
, tant que vous ne travaillez pas avec des chaînes Unicode.Si vous souhaitez stocker ce nouveau chaîne, vous aurez à
mystring = mystring.replace("1", "i")
. C'est parce que en Python les chaînes sont immuables.Voici un exemple d'utilisation de traduire commutateur "-" par "." et " majuscules "un"s
C'est beaucoup plus efficace que le retournement de tableau d'octets et en arrière si vous avez juste besoin de faire seul char remplacements
La question précise d'abord que les chaînes sont immuables et demande alors une façon de changer les choses en place. C'est un peu contradictoire. De toute façon, tant que cette question apparaît en haut de la liste lorsque vous effectuez une recherche pour "python chaîne en place de la modification", je suis en ajoutant la réponse pour un véritable changement endroit.
Chaînes semblent être immuable, lorsque vous observez les méthodes de la classe string. Mais pas de langage avec une interface pour le C peut fournir immuable types de données. La seule question est de savoir si vous devez écrire du code C afin d'obtenir la modification souhaitée.
Ici python
ctypes
est votre ami. Comme il supporte d'obtenir des pointeurs et comprend C-comme la mémoire des fonctions de copie, d'une chaîne python peut être modifié dans ce genre d'endroit:Résultats dans:
(Bien sûr, vous pouvez calculer la chaîne de remplacement au moment de l'exécution par l'application d'une fonction
F
pour chaque caractère de la chaîne d'origine. Différentes manières de le faire, cela a été indiqué dans la réponse à la question précédente.)Noter que je n'ai pas de toute façon encourager à faire cela. Cependant, j'ai dû écrire un remplacement pour une classe qui a été cartographié à partir de C++ python et inclus une méthode:
(L'appelant est censé fournir de la mémoire avec
length
octets et de la méthode, puis écrit les données disponibles-jusqu'àlength
-- dans cette mémoire, de retourner le nombre d'octets écrits.) Tout cela est parfaitement raisonnable de l'API en C/C++, il ne doit pas avoir été mis à la disposition de méthode d'une classe python ou au moins les utilisateurs de l'API doivent être informés qu'ils ne peuvent passer mutable tableaux d'octets en tant que paramètre.Comme vous vous en doutez, "usage commun" de la méthode est comme dans mon exemple (créer une chaîne de caractères et de les passer avec sa longueur comme arguments). Comme je n'ai pas vraiment envie d'écrire un C/C++ extension, j'ai dû trouver une solution pour mettre en œuvre le comportement dans la remplaçante de ma classe à l'aide de python seulement.
Si jamais j'ai besoin de faire quelque chose comme ça je viens de le convertir en mutable liste
Par exemple... (même si ce serait plus facile à utiliser de tri (voir le deuxième exemple) )
Vous pouvez utiliser StringIO classe de recevoir des fichiers comme mutable interface de la chaîne.