Python

[파이썬 스킬 업] 2장. 문자열 기능

patrick-star 2023. 4. 25. 23:20
728x90

2-1 문자열은 불변(immutable)

  • 불변 타입의 장점
    1) 딕셔너리의 키로 사용할 수 있다2) 불변 타입을 사용할 때 내부적으로 성능이 최적화되어 있는 데이터 타입을 사용할 수 있다.
    ex) 튜플리스트보다 더 효율적

    `movie_score = {'인셉션' : 5.0, '파벨만스' : 3.5, '헤어질 결심' : 4.0} # 딕셔너리의 키로 불변인 문자열을 사용할 수 있다`
  • 불변 타입의 단점
    1) 변경할 수 없다.하지만, 다음 코드는 동작한다.기존에 있던 문자열 값을 바꾸는게 아니라 새로운 문자열 객체를 생성하고 변수에 대입하기 때문에 문제가 없다.

`my_str = '안녕' my_str = '안녕하세요.'`
`my_str = '기린그림..' my_str[0] = '자' # 이때, error 발생`

2-2 바이너리를 포함한 숫자 변환

s = '45'
n = int(s) # 45가 출력됨 ==> 문자열 s가 int형으로 변환됨
x = float(s) # 45.0이 출력됨 ==> 문자열 s가 float형으로 변환됨

int('10001', 2) # 10001이라는 문자열을 2진수로 변환

int('775', 8) # 775라는 문자열을 8진수로 변환
int('1E', 2) # 1E이라는 문자열을 16진수로 변환


n = 1007 

str(n) # int형 변수 n을 문자열로 변환함 

# 만약에 정수의 길이를 알고 싶다면 아래와 같은 방법으로 알 수 있음
len(str(n)) 

2-3 문자열 연산자

연산자 설명
==, != 두 문자열이 같은지/다른지(대,소문자도 구분함)
<, >, <=, >= 알파벳 순서로 앞에 있는지 뒤에 있는지
+ 두 문자열 결합
문자열1 * n 문자열1을 n번 반복해서 연결함
문자열1 in, not in 문자열2 문자열1 전체가 문자열2에 포함되어 있는지 안 되어 있는지
문자열 is, is not 객체 문자열과 객체가 동일한 객체를 참조하고 있는지

2-4 인덱싱과 슬라이싱

문자열은 불변 타입이라서 인덱싱, 슬라이싱을 통해 실제 값을 변경할 수는 없다.
때문에 값을 추출하는 용도로 사용할 수 있다.

인덱싱 또는 슬라이싱을 할 때 알아두면 편한 문자열의 인덱스

안녕하십니까 
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1

이런식으로 이뤄져 있다고 생각하면 인덱싱, 슬라이싱을 좀 더 수월하게 할 수 있다.

s = '안녕하십니까' 

s[0] # '안' ,str 타입
s[-1] # '까' ,str 타입

s[2:5] # 하십니 (2 ~ (5-1)번째 값)  
s[:5] # 안녕하십니 (0 ~ (5-1)번째 값) 
s[2:] # 하십니까 (2 ~ 마지막 값)
s[:] # 안녕하십니까 (전체)

s[2::2] # 하니 (2 ~ 마지막 값을 뽑는데 2칸 간격으로 슬라이싱) 

s[::-1] # 까니십하녕안 (전체 문자열을 슬라이싱하는데 뒤에서부터 1칸씩) 

tip) 첫 문자와 마지막 문자 제거하기


king_str = '"헨리 8세"' # print로 출력하면 "헨리 8세" 

# 큰따옴표를 제거하고 싶을 때 아래와 같이 쓴다. 
king_str[1:-1] # 1번째에서 (-1-1)번째까지 
               # 1번째에서 (마지막 - 1)번째 까지 
               # python은 java처럼 길이 구해서 마지막 문자 인덱스를 굳이 구할 필요가 없다는 걸 알 수 있음

슬라이싱을 수행할 때 인덱스 범위를 벗어나도 예외를 발생시키지 않음

str_1 = 'cat'
str_2 = str_1[10:20] # b_str에는 빈 문자열이 대입됨 

2.5 ord, chr 메소드

ord('A') # 'A'의 아스키코드 65가 반환됨 

chr(65) # 아스키코드 65의 값을 가진 A가 반환됨 

ex) 문자열 안에 모음이 있는지 확인하기

s = 'elephant' 

# 첫 문자(s[0])를 대문자로 변환시키고 그 값이 AEIOU 중 하나인지 파악하는 코드
if s[0].upper() in 'AEIOU' :
    print('첫 문자는 모음')   

2.6 join을 통한 리스트에 있는 값들의 문자열 결합

문자열 결합은 앞서 + 연산자로 진행할 수 있다고 했다.
이 방법은 편리하지만 단점이 있는데 어떤 단점이 있는지 살펴보자.

ex)

str1 = 'Big ' 
str1 = str1 + 'Bad' 

# 이렇게 + 연산자를 이용하면 간결하게 표현할 수는 있겠지만
# 내부적으로 새로운 문자열을 생성하는 일을 반복하기 때문에 비효율적일 수 있다. 

그래서 join 메소드를 고안한다.

구분자_문자열.join(리스트) # 리스트에 있는 내용을 합쳐서 문자열로 만들고 싶을 때 사용할 수 있다. 

join 메소드를 사용함으로써 가비지 컬렉션에 의해서 버려질 문자열을 만들지 않아도 되고 가비지 컬렉션 수행 횟수 자체를 줄일 수 있다.

ex) join을 쓰지 않은 경우

print_nice(['Kim', 'Lee', 'Park', 'Choi']) 

def print_nice(a_lst):
    s = ''
    for item in a_lst:
        s += item + ', '
    if len(s) > 0 :
        s = s[:-2] 
    print(s) 
def print_nice(a_lst) : 
    print(','.join(a_lst)) 

a_lst 리스트에 있는 값들을 ,로 구분하고 싶어서 위와 같이 join을 사용했다.

2.9 간단한 boolean 메서드 & 2.10 대.소문자 변환 메서드

메서드 설명
str.isdigit() 최소 1개 이상의 문자가 있으면서 모든 문자가 10진수 숫자로 이루져 있는 경우 true
str.islower() 최소 1개 이상의 문자가 있으면서 모든 문자가 소문자로 이뤄진 경우 true
str.isupper() 최소 1개 이상의 문자가 있으면서 모든 문자가 대문자로 이뤄진 경우 true
메서드 설명
문자열.lower() 모든 문자열이 소문자로 바뀐 문자열을 생성
문자열.upper() 모든 문자열이 대문자로 바뀐 문자열을 생성
문자열.title() ex) 'foo foo'.title() ==> 'Foo Foo'
문자열.swapcase() 대소문자가 바뀐 문자열을 생성

2.11 검색-교체 메서드

'My Name...'.startswith('M') # 'My Name...' 이라는 문자열이 'M'으로 시작하는 경우 true 반환 
'My Name...'.startswith('Mv') # 'My Name...' 이라는 문자열이 'Mv'로 시작하는 경우 true 반환 


'Jake Rupin'.endswith('n') # 'Jake Rupin'이라는 문자열이 n으로 끝나는 경우 true 반환
'Jake Rupin'.endswith('in') # 'Jake Rupin'이라는 문자열이 in으로 끝나는 경우 true 반환
  • 문자열.count
frank_str = 'doo be doo be doo...' 

n = frank_str.count('doo') # 'doo'라는 부분 문자열이 나타난 횟수 3이 반환됨  
n = frank_str.count('doo', 1) # 'doo'라는 부분 문자열이 1번째 부터 시작해서 나타난 횟수 2가 반환됨  
n = frank_str.count('doo', 1, 10) # 'doo'라는 부분 문자열이 1번째 부터 10번째까지 나타난 횟수 1이 반환됨
  • 문자열.find
    frank_str = 'doo be doo be doo...'
    

n = frank_str.find('doo') # 'doo'라는 부분 문자열이 처음 나타난 인덱스 0을 반환함
n = frank_str.find('doo', 1) # 'doo'라는 부분 문자열이 1번째 부터 처음 나타난 인덱스 7이 반환됨
n = frank_str.find('doo', 1, 10) # 'doo'라는 부분 문자열이 1번째 부터 10번째까지 처음 나타난 인덱스 7이 반환됨


cf) 문자열.rfind => find와 달리 문자열의 마지막에서 부터 문자열 탐색
    문자열.index => find와 동일. 하지만, 부분 문자열을 찾지 못하면 예외 발생 

- 문자열.replace
``` python 
title = 'Greyer Into Grey'  
title.replace('Grey', 'Blue') # title 문자열에 있는 Grey 라는 문자열을 Blue로 바꾼다. 그래서 Blueer Into Blue가 반환된다.

# 교체 횟수를 정하고 싶다면 교체 횟수를 추가적으로 매개변수에 전달하면 된다 .
ex) title.replace('Grey', 'Blue', 2)

2.12 split을 활용한 입력 값 쪼개기 ⇒ 토근화(tokenizing) 작업에 쓰임

# 이렇게 되면 문자열 'Moe, Larry, Curly, Shemp'을 쉼표(,)로 구분해서 리스트가 만들어진다.
strong_list = 'Moe, Larry, Curly, Shemp'.split(',') # \['Moe', ' Larry', ' Curly', ' Shemp']

# 공백을 기준으로 구분하고 싶다면 split의 매개변수에 아무것도 쓰지 않으면 된다.
strong_list = 'Moe Larry Curly Shemp'.split() # \['Moe', 'Larry', 'Curly', 'Shemp']

# 물론, ' '와 같은 걸 넣을 수도 있지만 공백이 무조건 1칸으로만 띄워져 있지 않다면 아무런 값도 넣지 않는 것이 더 좋다.
# 왜냐하면, 빈칸이 4칸이라면 빈칸 1개를 제외한 나머지 3칸이 리스트에 저장되기 때문이다.

ex) strong_list = 'Moe Larry Curly Shemp'.split(' ') ==> ['Moe', '', '', 'Larry', '', 'Curly', '', '', '', 'Shemp']

# 콤마와 빈칸이 합쳐져 있는 경우 ==> 구분 문자열이 정확히 일치해야 한다.

strong_list = 'Moe, Larry, Curly, Shemp'.split(', ') # 각 문자열이 정확히 ', '로 떨어져 있다면 구분되도록 설정된다.  
=> \['Moe', 'Larry', 'Curly', 'Shemp']