[Python] TypeError: 'str' object does not support item assignment

kikichoigo·2024년 8월 2일
post-thumbnail

TypeError: 'str' object does not support item assignment

string은 요소의 수정이 불가능하다는 뜻이다.

프로그래머스 [1차] 프렌즈 4블록
해당 문제를 풀다가 초반에 이 에러를 만났다.


입력이 위 사진 처럼 List 안에 String으로 주어지는데, 이 문자열(string)의 요소를 변경하려고 했기 때문이다.

위 에러는 문자열을 list(str)으로 변경해 문자열의 아이템 하나하나들을 list의 요소로 만들어 요소를 변경가능하도록 하여 해결했다.

text = "Hallo World"
print(text)
# Hallo World

print(text[1])
# a
print(text[1:3])
# al

text[1] = 'e'
# TypeError: 'str' object does not support item assignment

위 예시처럼 문자열은 인덱스로 접근 가능하다. 또한 슬라이싱도 가능하다.
하지만 요소의 값을 바꾸는 것은 불가능하다.

왜 인덱스로 접근은 가능한데 인덱스로 접근해 요소의 값을 변경하는 것은 불가능할까?

원인

자료형의 종류에는 수정이 가능한 객체인 mutable 타입(리스트, 딕셔너리 등)이 있고,
수정이 불가능한 객체인 immutable 타입(튜플, 문자열 등)이 있는데
문자열을 immmutable한 자료형이라서 위와 같이 인덱싱(혹은 슬라이싱)을 통한 값 수정이 불가능하다.

해결 방법

1. 문자열 수동할당

문자열 덧셈 연산으로 이어 붙이기가 되는 점을 이용해 재할당을 하는 방법이다.
다만, 이 방법은 값을 수정할 때마다, 문자열 길이 N에 대하여 O(N)의 시간 복잡도가 소요된다.

text = text[:1] + 'e' + text[2:]
print(text)
# Hello World

2. 리스트로 변환해 수정

내가 위 문제를 풀면서 쓴 방법이다.
잦은 수정이 필요한 경우, mutable 타입 객체인 리스트로 변환해둔 뒤 수정을 진행하면 값 변경 시에 O(1)의 시간복잡도가 소요되므로 수동할당보다 훨씬 유리하다.

text = 'hello world'
text = list(text)
print(text)
# ['h', 'e', ...]

text[1] = 'a'
print(text)
# ['h', 'a', ...]

text = ''.join(text)
print(text)
# hello world

join 메서드를 이용하면 리스트를 문자열로 변환할 수 있다.

3. replace 이용

replace 메서드를 이용해 바뀔 문자(old)와 바꿀 문자(new) 매개변수로 전달해주면 문자열에서 아이템을 바꿀 수 있다.

text = 'hello world'

text.replace('e', 'a')
print(text)
# hallo world

replace의 매개변수로 숫자를 넣으면 그만큼의 문자가 바뀐다. 예시로

text = 'aaaaaaaaa'
text.replace('a', 'e', 3)
print(text)
# eeeaaaaaa

매개변수를 넣지 않으면 모든 해당문자가 변경되고,
매개변수로 자연수를 넣으면 그 숫자만큼 앞에서부터 변경된다.

replace의 시간복잡도는 (문자열의 길이 * (교체할 문자열의 길이 + 교체되는 문자열의 길이/교체할 문자열의 길이))이다.
즉, str.replace(a, b)라면 O(len(str) * (len(a) + len(b)/len(a)))이다.

replace 함수는 문자열 str의 길이만큼 전체적으로 문자열을 하나씩 탐색하고 교체할 문자열의 길이만큼 이전값을 탐색해서 교체해야하는 문자열인지 아닌지를 판별한다.
교체해야 하는 경우, 교체되는 문자열의 길이에 따라 추가 연산이 필요하다.

교체되는 문자열의 길이가 교체할 문자열의 길이와 같은 경우, 할당된 길이만큼(교체할 문자열의 길이만큼)만 연산을 수행하면 되기 때문에 O(len(b)/len(a)) = O(1)로 상수의 시간이 소요된다.

교체되는 문자열의 길이가 교체할 문자열의 길이보다 큰 경우, 초과된 길이만큼 새 위치를 만들고 교체가 이뤄지므로 O(len(b)/len(a))만큼의 추가 연산이 소요된다.

0개의 댓글