532 votes

Changer un caractère dans une chaîne de caractères

Quel est le moyen le plus simple en Python de remplacer un caractère dans une chaîne de caractères ?

Par exemple :

text = "abcdefg";
text[1] = "Z";
           ^

725voto

scvalex Points 5626

Ne modifiez pas les cordes.

Utilisez-les comme des listes et ne les transformez en chaînes de caractères qu'en cas de besoin.

>>> s = list("Hello zorld")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'z', 'o', 'r', 'l', 'd']
>>> s[6] = 'W'
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello World'

Les chaînes Python sont immuables (c'est-à-dire qu'elles ne peuvent pas être modifiées). Il existe beaucoup de raisons pour cela. Utilisez les listes jusqu'à ce que vous n'ayez plus le choix, puis transformez-les en chaînes de caractères.

14 votes

Ceux qui recherchent la rapidité/efficacité, lisez ceci

26 votes

"Ne pas modifier les chaînes de caractères." pourquoi

5 votes

"Créer->modifier->sérialiser->assigner->libérer" plus efficace que s[6]='W' ? Hmm... Pourquoi d'autres langages l'autorisent-ils, malgré ces "nombreuses" raisons ? Il est intéressant de voir comment une conception étrange peut être défendue (par amour, je suppose). Pourquoi ne pas suggérer l'ajout d'une fonction MID(strVar,index,newChar) au noyau de Python qui accède directement à la position mémoire du caractère, au lieu de mélanger inutilement les octets de la chaîne entière ?

296voto

Mehdi Nellen Points 484

La méthode la plus rapide ?

Il existe trois méthodes. Pour les amateurs de vitesse, je recommande la "méthode 2".

Méthode 1

Compte tenu de ce réponse

text = 'abcdefg'
new = list(text)
new[6] = 'W'
''.join(new)

Ce qui est plutôt lent comparé à "Méthode 2".

timeit.timeit("text = 'abcdefg'; s = list(text); s[6] = 'W'; ''.join(s)", number=1000000)
1.0411581993103027

Méthode 2 (MÉTHODE RAPIDE)

Compte tenu de ce réponse

text = 'abcdefg'
text = text[:1] + 'Z' + text[2:]

Ce qui est beaucoup plus rapide :

timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
0.34651994705200195

Méthode 3 :

Tableau d'octets :

timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)
1.0387420654296875

2 votes

Il serait intéressant de voir comment elle se comporte par rapport à la méthode bytearray également.

2 votes

Bonne suggestion. La méthode bytearray est également plus lente : timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000) deux fois plus lent que le plus rapide.

0 votes

Merci Mehdi pour le test. J'ai essayé sur mon ordinateur : bytearray est trois fois plus lent que la méthode la plus rapide (méthode 2), mais plus rapide que list (qui est cinq fois plus lent que la méthode la plus rapide). Donc bytearray n'est pas le plus rapide, mais c'est toujours une meilleure alternative à list pour les manipulations plus compliquées sur les chaînes de caractères.

150voto

Jochen Ritzel Points 42916
new = text[:1] + 'Z' + text[2:]

2 votes

Si vous ne comprenez pas pourquoi ça marche, voir la réponse ci-dessous

56voto

Martin Beckett Points 60406

Les chaînes Python sont immuables, vous les modifiez en faisant une copie.
La façon la plus simple de faire ce que vous voulez est probablement :

text = "Z" + text[1:]

Le site text[1:] renvoie la chaîne de caractères dans text de la position 1 à la fin, les positions sont comptées à partir de 0, donc '1' est le deuxième caractère.

éditer : Vous pouvez utiliser la même technique de découpage de la chaîne pour n'importe quelle partie de la chaîne.

text = text[:1] + "Z" + text[2:]

Si la lettre n'apparaît qu'une seule fois, vous pouvez utiliser la technique de recherche et de remplacement proposée. ci-dessous

0 votes

Il s'agit du 2ème caractère, c'est-à-dire le caractère à la place numéro 1 (par opposition au 1er caractère, numéro 0).

14voto

Mahmoud Points 11

À partir de python 2.6 et python 3, vous pouvez utiliser des bytearrays qui sont mutables (peuvent être modifiés élément par élément, contrairement aux chaînes de caractères) :

s = "abcdefg"
b_s = bytearray(s)
b_s[1] = "Z"
s = str(b_s)
print s
aZcdefg

edit : Changé str en s

edit2 : Comme Two-Bit Alchemist l'a mentionné dans les commentaires, ce code ne fonctionne pas avec l'unicode.

1 votes

Cette réponse est incorrecte. D'une part, elle devrait être bytearray(s) pas bytearray(str) . Pour un autre, cela produira : TypeError: string argument without an encoding . Si vous spécifiez un encodage, vous obtenez alors TypeError: an integer is required . C'est avec l'unicode de Python 3 ou de Python 2. Si vous faites cela en Python 2 (avec une deuxième ligne corrigée), cela ne fonctionnera pas pour les caractères non ASCII car ils peuvent ne pas être constitués d'un seul octet. Essayez-le avec s = 'Héllo' et vous obtiendrez 'He\xa9llo' .

0 votes

J'ai réessayé sur Python 2.7.9. Je n'ai pas pu régénérer l'erreur que vous mentionnez (TypeError : string argument without an encoding).

0 votes

Cette erreur ne s'applique que si vous utilisez l'unicode. Essayez s = u'abcdefg' .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X