파이썬에서 문자열에서 한 문자 변경


385

파이썬에서 문자열의 문자를 바꾸는 가장 쉬운 방법은 무엇입니까?

예를 들면 다음과 같습니다.

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

답변:


534

문자열을 수정하지 마십시오.

그것들을 목록으로 사용하십시오. 필요할 때만 문자열로 바꾸십시오.

>>> 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'

파이썬 문자열은 변경할 수 없습니다 (즉, 수정할 수 없습니다). 여기에는 많은 이유가 있습니다. 선택의 여지가 없을 때까지 목록을 사용하고 나서 만 문자열로 바꾸십시오.


4
속도 / 효율을 찾는 사람들은 이것을 읽으십시오
AneesAhmed777

4
"문자열을 수정하지 마십시오." 왜
hacksoi

2
s [6] = 'W'보다 "생성-> 수정-> 직렬화-> 할당-> 무료"? 흠 ... 왜 그런 "많은"이유에도 불구하고 다른 언어가 허용합니까? 이상한 디자인을 어떻게 방어 할 수 있는지에 관심이 있습니다. 전체 문자열로 불필요하게 바이트 셔플 링 대신 char 메모리 위치에 직접 액세스하는 함수 MID (strVar, index, newChar)를 Python 코어에 추가하는 것이 좋습니다.
oscar

@hacksoi, @oscar, 그 이유는 매우 간단합니다. 수정 할 때 복사를 구현하기 위해 포인터를 전달할 때 다시 계산 할 필요가 없거나 누군가가 해당 문자열을 수정하려는 경우 전체 문자열을 완전히 복사하면 일반적인 속도가 증가합니다. 사용하다. MID슬라이스로 인해 필요한 것은 없습니다 :s[:index] + c + s[index+1:]
MultiSkill

1
@oscar 멍청한 언어는 명시 적으로 말하지 않으면 유니 코드를 다루지 않는다는 것을 의미합니다. 물론 C로 유니 코드 가능 응용 프로그램을 작성할 수 있습니다. 그러나 항상 신경 써야하고 문제를 피하기 위해 명시 적으로 테스트해야합니다. 모든 것이 기계 지향적입니다. 파이썬을 배우기 전에 PHP와 함께 일했고 그 언어는 완전히 혼란입니다. 빠른 CPU에 대한 메모와 관련하여 전적으로 귀하와 함께합니다. 그러나 그 문제의 일부는 대중적인 조기 최적화에 대한 비 승인입니다. 이로 인해 많은 CPU 사이클이 유출되어 인터프리터와 라이브러리가 느려집니다.
Bachsau

202

가장 빠른 방법?

세 가지 방법이 있습니다. 스피드를 찾는 사람들에게는 '방법 2'를 추천합니다

방법 1

답변으로 주어진

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

'방법 2'에 비해 속도가 느립니다.

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

방법 2 (빠른 방법)

답변으로 주어진

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

훨씬 빠릅니다 :

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

방법 3 :

바이트 배열 :

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

1
그것이 bytearray 방법에 비해 어떻게 진행되는지 보는 것이 흥미로울 것입니다.
gaborous

1
좋은 제안. bytearray 방법도 느립니다 : timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)가장 빠른 것 보다 두 배 느립니다.
Mehdi Nellen

2
테스트를 이해하면 파이썬 문자열을 어떻게 조작해야하는지 다시 생각할 수 있습니다.
Spectral

1
좋은. 방법 3도 포함하도록 답을 편집하십시오 (바이트 배열).
AneesAhmed777

1
여기서 대부분의 시간은 변환에 사용됩니다 ... (문자열-> 바이트 배열). 문자열을 편집하기 위해 많은 편집 작업이 있으면 바이트 배열 방법이 더 빠릅니다.
Ian Sudbery


37

파이썬 문자열은 변경할 수 없으므로 복사하여 변경합니다.
원하는 것을 수행하는 가장 쉬운 방법은 아마도 다음과 같습니다.

text = "Z" + text[1:]

text[1:]문자열 text은 위치 1에서 끝까지 문자열을 반환하고 위치는 0부터 카운트하므로 '1'은 두 번째 문자입니다.

편집 : 문자열의 모든 부분에 동일한 문자열 슬라이싱 기술을 사용할 수 있습니다

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

또는 글자가 한 번만 나타나는 경우 아래 제안 된 검색 및 바꾸기 기술을 사용할 수 있습니다


나는 두 번째 캐릭터 인 IE를 언급합니다. 장소 번호 1의 문자 (첫 번째 문자, 숫자 0에 해당)
kostia

텍스트 [0] + "Z"+ 텍스트 [2 :]
wbg

13

python 2.6 및 python 3부터는 변경할 수있는 바이트 배열을 사용할 수 있습니다 (문자열과 달리 요소별로 변경 가능).

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

편집 : str을 s로 변경

edit2 : 주석에서 언급 한 2 비트 연금술사처럼이 코드는 유니 코드와 함께 작동하지 않습니다.


이 답변은 잘못되었습니다. 우선 bytearray(s), 그렇지 않아야 bytearray(str)합니다. 다른 경우에는 다음이 생성 TypeError: string argument without an encoding됩니다.. 인코딩을 지정하면 얻을 수 TypeError: an integer is required있습니다. 그것은 Python 3 또는 Python 2의 유니 코드입니다. 두 번째 줄이 수정 된 Python 2 에서이 작업을 수행하면 ASCII가 아닌 문자는 1 바이트가 아니기 때문에 작동하지 않습니다. 그것을 시도 s = 'Héllo'하고 당신은 얻을 것이다 'He\xa9llo'.
2 비트 연금술사

파이썬 2.7.9에서 다시 시도했습니다. 언급 한 오류 (TypeError : 인코딩없는 문자열 인수)를 다시 생성 할 수 없습니다.
Mahmoud

이 오류는 유니 코드를 사용하는 경우에만 적용됩니다. 시도하십시오 s = u'abcdefg'.
2 비트 연금술사

4
이것을하지 마십시오. 이 방법은 문자열 인코딩의 전체 개념을 무시하므로 ASCII 문자에서만 작동합니다. 현재는 영어권 국가의 영어 사용자라도 ASCII를 가정 할 수 없습니다. 파이썬 3의 가장 큰 하위 비 호환성 및 가장 중요한 견해로는이 전체 바이트 = 문자열 거짓 동등성을 수정하는 것입니다. 다시 가져 오지 마십시오.
Adam

5

다른 사람들이 말했듯이 일반적으로 파이썬 문자열은 변경할 수 없습니다.

그러나 python.org에서 구현 한 CPython을 사용하는 경우 ctypes를 사용하여 메모리의 문자열 구조를 수정할 수 있습니다.

다음은이 기술을 사용하여 문자열을 지우는 예입니다.

파이썬에서 데이터를 민감한 것으로 표시

나는 완전성을 위해 이것을 언급하고, 이것이 해킹이기 때문에 이것이 최후의 수단이되어야합니다.


6
최후의 조치? 당신이 경우 지금까지 이렇게 갑자기 악으로 브랜드있다!
Chris Morgan

문자열에 비밀번호가 포함 된 경우 @ChrisMorgan 비밀번호가 메모리 어딘가에 기록되므로 s = ''로 지우는 것만으로는 충분하지 않습니다. ctypes를 통해 지우는 것이 유일한 방법입니다.
Cabu

1
@Cabu 나는 것이 결코 에서 모든 것을 한 코드를 받아 들일 상황. 데이터가 민감하고 이와 같은 보안이 필요한 str경우 올바른 유형이 아닙니다. 그냥 사용하지 마십시오. bytearray대신 비슷한 것을 사용하십시오 . (아직도 우연히 데이터를 불투명 한 데이터로 취급 하여 실수로 데이터를 검색 할 수 없도록str 사고에서 보호합니다. 라이브러리는있을 수 있습니다.)
Chris Morgan

4

이 코드는 내 것이 아닙니다. 나는 그곳에서 가져온 사이트 양식을 기억하지 못했습니다. 흥미롭게도이 문자를 사용하여 하나 이상의 문자를 하나 이상의 문자로 바꿀 수 있습니다. 이 답변은 매우 늦었지만 나와 같은 초보자는 언제든지 유용 할 수 있습니다.

텍스트 변경 기능.

mytext = 'Hello Zorld'
mytext = mytext.replace('Z', 'W')
print mytext,

11
이것은 질문에 대답하지 않습니다. 전혀 원하는 것이 아닙니다.
Chris Morgan

2
첫 번째 코드 바꾸려면이 코드가 잘못되었습니다 l. mytext = mytext.replace('l', 'W')->HeWWo Zorld
Ooker

수술 적으로 1 문자 만 바꾸려고하면 (이것은) 청구서에 완벽하게 맞습니다. 감사!
ProfVersaggi

@ProfVersaggi 그건 사실이 아닙니다. 위의 Ooker의 의견을 참조하십시오.
2 비트 연금술사

3
@Ooker 첫 문자 바꾸려면 사용할 수 있습니다 mytext = mytext.replace('l', 'W',1). 문서 링크
Alex

2

실제로 문자열을 사용하면 다음과 같이 할 수 있습니다.

oldStr = 'Hello World!'    
newStr = ''

for i in oldStr:  
    if 'a' < i < 'z':    
        newStr += chr(ord(i)-32)     
    else:      
        newStr += i
print(newStr)

'HELLO WORLD!'

기본적으로 새 문자열에 "+"문자열을 함께 추가하고 있습니다 :).


4
모든 연결이 불변이기 때문에 모든 문자열 객체가 새로운 문자열 객체를 생성해야하기 때문에 이것은 매우 느릴 것입니다.이 질문에 관한 것입니다.
2 비트 연금술사

0

귀하의 세계가 100 % 인 경우 ascii/utf-8(많은 사용 사례가 해당 상자에 적합) :

b = bytearray(s, 'utf-8')
# process - e.g., lowercasing: 
#    b[0] = b[i+1] - 32
s = str(b, 'utf-8')

파이썬 3.7.3


0

문자열에서 문자를 변경하는 다른 방법을 추가하고 싶습니다.

>>> text = '~~~~~~~~~~~'
>>> text = text[:1] + (text[1:].replace(text[0], '+', 1))
'~+~~~~~~~~~'

문자열을 목록으로 바꾸고 i 번째 값을 바꾸고 다시 결합하는 것과 비교할 때 얼마나 빠릅니까?

접근 방식

>>> timeit.timeit("text = '~~~~~~~~~~~'; s = list(text); s[1] = '+'; ''.join(s)", number=1000000)
0.8268570480013295

내 솔루션

>>> timeit.timeit("text = '~~~~~~~~~~~'; text=text[:1] + (text[1:].replace(text[0], '+', 1))", number=1000000)
0.588400217000526
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.