본문 바로가기

Python

[Python] 2. 파이썬의 기본 자료형(2) - 문자열(String)

반응형

 

파이썬에서 문자열을 다루는 방법은 정말 다양하다. 특히 C/C++을 먼저 학습한 사람이라면 더 쉽고 다양한 방식이 많다는 것을 체감할 것이다.

 

 

[목차]

 

1. 문자열 만들기

 

2. 문자열 연산하기

 

3. 문자열 인덱싱

 

4. 문자열 슬라이싱

 

5. 문자열 포매팅

 

6. 문자열 관련 함수

 

  1. 문자열 만들기

 

문자열은 ' ' (작은따옴표), " " (큰따옴표), ''' ''' (작은따옴표 3개), """ """ (큰따옴표 3개) 이들을 이용하여 하나의 문자열로 묶을 수 있다. 

이렇게 다양한 방법을 제공하는 이유는, 문자열 내에 따옴표가 포함될 수도 있기 때문이다. 

예를 들어서 I'm Python을 만들고 싶다면, 문자열 안에 작은따옴표가 있기 때문에 해당 문자열을 작은따옴표로 묶게 되면, 'I'm Python'이 되어버리므로 작은따옴표가 끝나는 지점을 올바르게 나타낼 수 없게 된다.

따라서 "I'm Python"과 같이 사용한다.  

 

그리고 ''' ''' 또는 """ """은 여러 줄로 된 문자열을 사용할 때 이용한다. 물론 한 줄로 사용해도 무방하다.

아래의 예시들을 살펴보자. 각 주석이 a를 출력했을 때 나타나는 결과이다.

a = "hello world"
print(a) # hello world

a = 'hello'
print(a) # hello

a = "I'm John" 
print(a) # I'm John

a = '''He said "It's good"'''
print(a) # He said "It's good"

a = '"Do python"'
print(a) # "Do python"

a = '''Life is short
do
python'''

print(a)
#Life is short
#do
#python

 

여러 줄인 문자열을 이용하는 또 다른 방법은, 문자열 안에 줄 바꿈 문자인 '\n'을 넣어주면 된다.

a = '''Life is short
do
python'''

a = "Life is short\ndo\npython"

 

이 두 코드는 동일한 문자열을 나타낸다. '\n'과 같은 백슬래시를 조합한 코드를 '이스케이프 코드(escape code)'라고 한다. 이스케이프 코드는 프로그래밍할 때 사용할 수 있도록 미리 정의해 둔 '문자 조합'이다. 

주로 사용하는 이스케이프 코드들은 다음과 같다. 

\n 문자열 안에서 줄을 바꿀 때 사용
\t 문자열 사이에 탭 간격을 줄 때 사용
\\ 문자 \를 그대로 표현할 때 사용
\' 작은따옴표(')를 그대로 표현할 때 사용
\" 큰따옴표(")를 그대로 표현할 때 사용

 

 

  2. 문자열 연산하기

 

파이썬에서는 문자열을 정수처럼 더하거나 곱할 수 있다. 

문자열을 더한다는 의미는 두 문자열을 이어 붙인다는 의미이고, 문자열을 곱한다는 의미는 문자열 * 숫자로 나타내어 해당 숫자만큼 문자열을 이어 붙인다는 의미이다.

 

a = "python"
b = "hello"

print(a*2) # ans : pythonpython

print(a+b) # ans : pythonhello

print(b+a) # ans : hellopython

a = a*3
print(a)   # ans : pythonpythonpython

a = a+b
print(b+a) # ans : hellopythonhello

print('='*10) # ans : ==========

 

 

  3. 문자열 인덱싱

 

인덱싱(indexing)은 어떤 것을 '가리킨다'는 의미이다.

 

문자열을 이루는 각각의 문자마다 위치를 나타내는 인덱스(index)가 존재한다. 

다른 언어들과 마찬가지로 파이썬도 시작 인덱스를 0으로 갖는다. 

예를 들어 문자열을 S라고 할 때, 'S[3]'은 S의 4번째 문자열을 나타낸다. 

"Do python"이라는 문자열이 있다고 하자. 그러면 인덱스는 다음과 같다. 

  D o   p y t h o n
Index 0 1 2 3 4 5 6 7 8

이 문자열의 1번째 문자는 'D', 3번째 문자는 ' ' (공백) , 8번째 문자는 'o'이다.

따라서 S[0] = 'D', S[2] = ' ', S[7] = 'o'가 된다. 

 

S = 'Do python'
print(S[0]) # 'D'

print(S[2]) # ' '

print(S[7]) # 'o'

print(S[-1]) # 'n'

print(S[-2]) # 'o'

 

0번이 제일 처음이라고 하였는데 음수는 무엇일까? 

인덱스에 음수를 쓰게 되면, 문자열을 뒤에서부터 읽게 된다. 따라서 S[-2]는 뒤에서 두 번째 문자인 'o'를 나타낸다. 

여기서 주의해야 할 점은 앞에서부터 읽는 경우에는 0부터 시작하지만, 뒤에서부터 읽는 경우에는 1부터 시작한다. 

-0은 결국 0이기 때문에 이를 구분하기 위함이다. 

 

 

 

  4. 문자열 슬라이싱

 

슬라이싱(slicing)은 어떤 것을 '잘라낸다'는 의미이다. 문자열을 슬라이싱 한다는 의미는 뭘까? 

 

"Do python"에서 4번째 문자부터 7번째 문자까지 뽑아내고 싶다고 가정하자. 

S[3] + S[4] + S[5] + S[6]으로 단순하게 뽑아낼 수 있다. 

하지만 슬라이싱 기법을 이용하면 더 간단하게 뽑아낼 수 있다. S[3:7]이 S[3] + S[4] + S[5] + S[6]과 동일하다.

 

사용하는 방식은 '변수명[시작지점 : 끝나는지점+1]' 로 이용한다. 

즉, S[a:b]은 문자열 S에서 a번째 문자부터 b-1번째 문자까지를 의미한다. [a, b)에 해당하는 부분 문자열이다. 

S[:b]로 사용하면 문자열의 처음부터 b-1번째 문자까지를 의미하며, S[a:]로 사용하면 a번째 문자부터 문자열의 끝까지를 의미한다. 

슬라이싱에서도 인덱싱과 마찬가지로 마이너스(-) 기호를 사용할 수 있다. 

S[2:-3] 이 뜻하는 것은 S[2]부터 S[-4]까지를 의미한다. 

 

슬라이싱을 이용해서 여러 응용을 할 수 있다. 아래 예시를 참고하자.

s = "helloworld"
s1 = s[:5]
s2 = s[5:]
#문자열 반으로 나누기 s1 = hello / s2 = world

#문자열의 특정 문자 바꾸기
a = s[:4] + 'a' + s[5:] # "hellaworld"

 

s[4]를 'a'로 바꾸기 위해서 s[4] = 'a'라는 코드를 생각해볼 수도 있다. 하지만 이렇게 작성하면 에러가 발생한다.

파이썬에서 문자열은 immutable 한 자료형, 즉 바꿀 수 없는 자료형이기 때문이다. 

따라서 문자열 안의 특정 문자를 바꾸고 싶은 경우에는 슬라이싱을 통해서 새로운 문자열을 만드는 방식으로 해결할 수 있다.

 

 

  5. 문자열 포매팅

 

문자열 포매팅(Formatting)은 문자열 내의 특정한 값을 바꿔야 할 경우가 있을 때 이용하는 방법이다.

제일 간단한 예시로는 시간이다. 

"현재 시간은 12시 25분입니다"와 같이 현재 시간을 문자열로 나타낸다고 하면, 1분이 지났을 때는

"현재 시간은 12시 26분입니다"로 나타내야 한다. 

단순한 방법으로는 모든 시간마다 문자열을 만들어서 출력하는 방식인데, 생각만 해도 번거롭다.

이런 상황에서 포매팅을 이용할 수 있다.

 

포매팅을 하는 방법은 크게 두 가지로 나뉜다. 서식 지정자를 이용하거나, format 메소드를 이용하는 방법이다.

 

 

1) 서식 지정자로 문자열 포매팅

 

서식 지정자(format specifier)는 다음과 같은 것들이 있다.

코드 설명
%s 문자열(String)
%c 문자 1개(Character)
%d 정수(Integer)
%f 부동 소수(floating-point)
%o 8진수
%x 16진수
%% 문자 '%' 자체

 

이제 이를 어떻게 사용하는지 알아보자.

먼저, 서식 지정자를 사용하기 위해서는 바꾸고 싶은 위치에 서식 지정자를 넣고, 문자열 뒤에 '% 값'을 추가해준다.

print("현재 시간은 %d시 입니다." %12)

 

위의 코드를 실행하면 "현재 시간은 12시입니다."가 출력된다. 

a = 12
print("현재 시간은 %d시 입니다." %a)

 

이렇게 해도 결과는 동일하다.

따라서, 이를 이용하면 시간이 달라질 때마다 변수의 값만 계속해서 바꿔주면 되므로 훨씬 편리하다. 

 

만약 문자열이나 실수 등 다른 타입을 넣고 싶다면 %s, %f 등으로 이용해주면 된다. 

2개 이상의 값을 넣는 경우에는 문자열 뒤에 %(a, b,...)으로 사용할 수 있다. 

예시를 통해서 이해해보자.

hour = 12
minute = 25
print("현재 시간은 %d시 %d분입니다." %(hour, minute))

name = "철수"
height = 180
weight = 80
print("%s의 키는 %d이고, 몸무게는 %d입니다." %(name, height, weight))

 

서식 지정자를 더 유용하게 사용하는 방법이 있다. 

서식 지정자 사이에 숫자를 넣으면 정렬과 공백 기능을 사용할 수 있다.

'%10s', '%2d'와 같이 % 와 문자 사이에 숫자를 넣게 되면 해당 숫자만큼의 길이를 가지면서 빈 공간은 공백으로 두고 오른쪽 정렬을 하여 출력해준다. 

print('숫자 출력%10d.' %100)
# ans : 숫자 출력       100.

print('숫자 출력%10d.' %10000)
# ans : 숫자 출력     10000.

print('숫자 출력%-10d.' %10000)
# ans : 숫자 출력10000     .

print('문자열 출력%10s.'%'string')
# ans : 문자열 출력    string.

 

만약 수가 음수이면 왼쪽 정렬을 시켜준다는 의미이다. 

 

서식 지정자를 이용해서 실수를 출력해줄 때 소수점 이하 자릿수를 지정할 수도 있다. 

'%.자릿수f' % 실수 처럼 이용하면 원하는 자릿수를 출력해줄 수 있다. (점도 하나의 문자 크기를 갖는다)

print('%.2f' %1.2)
# ans : 1.20

print('%.3f' %1.2)
# ans : 1.200

print('%10.2f' %1.2)
# ans :       1.20   

print('%10.3f' %1.2)
# ans :      1.200

 

 

2) format 메소드로 문자열 포매팅

 

format 메소드를 이용하면 조금 더 간편하게 문자열을 포매팅할 수 있다.

사용 방법은, 중괄호 { } 안에 인덱스를 지정하고 format 메소드로 값을 넣어준다.

format 메소드 안의 원소들이 인덱스에 맞게 문자열에 대입되며, 여러 값을 넣거나 같은 값을 여러 개 넣을 수 있다. 

만약 인덱스를 지정하지 않는다면 format 메소드에 입력한 순서대로 대입된다. 

아래 예시를 통해 확인해보자.

 

print('hello {0}'.format('world'))
# ans : hello world

print('hello {0}. Do {1}'.format('world', 'python'))
# ans : hello world. Do python

print('{1} {0} {2}'.format('am', 'I', 'Rebro'))
# ans : I am Rebro

print('{0} {0} {1} {1}'.format('python', 'C++'))
# ans : python python C++ C++

print('I {} {}'.format('like', 'apple'))
# ans : I like apple

s = 'I want to play {0}'
print(s.format('soccer'))
# ans : I want to play soccer

 

꼭 인덱스를 이용하지 않아도 포매팅이 가능하다. 인덱스를 다루기가 힘들다면 이름을 지정해도 된다.

또, 파이썬 3.6부터는 문자열 포매팅에 변수를 그대로 사용할 수 있다. 이 경우에는 문자열 앞에 포매팅이라는 의미로 f를 붙여준다.

 

추가적으로, 중괄호 자체를 사용하고 싶다면 중괄호를 두 개 사용하면 된다.

print('{name} is {job}'.format(name = 'John', job = 'programmer'))
# ans : John is programmer

# since python 3.6 
name = 'John'
work = 'studying'
print(f'{name} is {work}')
# ans : John is studying

print('{{ {0} }}'.format('python'))
# ans : { python }

 

서식 지정자와 마찬가지로 정렬도 가능하다. 

인덱스 다음에 :>숫자 (오른쪽 정렬)과 같은 방식으로 가능하다. 

또 실수를 나타낼 때 소수점 자리를 지정해주는 것도 가능하다.

예시를 통해 이해해보자.

 

print('{0:>10}'.format('hi')) # > : 오른쪽 정렬
# ans :         hi

print('{0:<10}'.format('hi')) # < : 왼쪽 정렬
# ans : hi        

print('{0:^10}'.format('hi')) # ^ : 가운데 정렬
# ans :     hi    

print('{0:=^10}'.format('hi')) # 빈공간 '='로 채우기
# ans : ====hi====

print('{0:!<10}'.format('hi'))
# ans : hi!!!!!!!!

print('{0:10.4f}'.format(4.2))
# ans :    4.2000

print('{0:10.2f}'.format(4.2))
# ans :      4.20

a = 4.2
print(f'{a:10.3f}')
# ans :     4.200

 

 

  6. 문자열 관련 함수

 

함수 설명 예시
 count 문자열 중 해당 문자의 개수를 반환한다.  S.count('a')
 find / rfind 문자열 중 해당 문자 또는 문자열의 첫번째 위치를 반환한다. 존재하지 않는다면 -1을 반환한다.

rfind는 오른쪽에서부터 첫번째 위치를 반환한다.
 S.find('a') / S.find("abc") / S.rfind('a')
 index / rindex find와 같지만, 존재하지 않는 경우에 -1을 반환하지 않고 오류를 발생시킨다. 

rindex는 오른쪽에서부터 첫번째 위치를 반환한다.
 S.index('a') / S.rindex("abc")
 split 특정 값을 구분자로 하여 문자열을 분리하고, 분리된 문자열들은 리스트에 담겨 반환된다.

split의 괄호 안에 아무것도 넣지 않으면 공백(space, tap, enter)을 구분자로 갖는다. 
 S.split() / S.split(',') / S.split(':') 
 strip / rstrip / lstrip 문자열의 양쪽 끝에 있는 해당 문자들을 모두 제거한다. 아무것도 넣지 않으면 양쪽 끝의 공백을 모두 제거한다. 

rstrip, lstrip 함수를 이용하여 오른쪽 끝 또는 왼쪽 끝만 제거할 수도 있다.
 S.strip() / S.strip(',.') / S.strip(':,.q') 

 S.rstrip() / S.lstrip()
 join(문자열) 각각의 문자열 사이에 지정한 문자를 삽입한다.  ",".join("abcd")  (=> "a,b,c,d")
 join(튜플, 리스트) 리스트나 튜플을 넣으면 지정한 문자들이 삽입된 문자열을 반환한다.  " ".join([a,b,c])  (=> "a b c")
 upper / lower upper는 소문자를 대문자로, lower는 대문자를 소문자로 바꿔준다.  S.lower() / S.upper()
 replace 문자열안의 특정 문자열을 다른 문자열로 바꾼 결과를 반환한다. (원래 문자열은 바뀌지 않는다)  S.replace("abc", "def") 
 maketrans / translate 문자열안의 특정 문자를 다른 문자로 바꾸는 함수이다.
maketrans 함수로 미리 문자별로 매칭을 시켜놓는다. 
 table = str.maketrans('abc', '2f4')
 S = 'cbaa'
 S.translate(table) (=> '4f22')
 ljust / rjust / center 문자열의 길이를 지정하고, 해당 길이 내에서 정렬해주는 함수이다.

ljust는 왼쪽 정렬, rjust는 오른쪽 정렬, center는 가운데 정렬이다.
 S.ljust() / S.rjust() / S.center()
 zfill 지정된 길이에 맞춰서 앞에 0을 채워준다.

기존의 문자열 길이보다 작다면 아무것도 채우지 않는다.
 "abc".zfill(6) (=> "000abc")

 

추가적으로, 문자열의 함수들은 문자열을 처리한 결과를 반환하기 때문에, 해당 결과를 가지고 또 함수를 이용할 수 있다. 따라서 메소드들을 연결해서 한 번에 처리할 수 있고 이를 '메소드 체이닝(method chaining)이라고 한다.

ex) 'python'.ljust(10).upper()

 

 

 

PC로 보시는 것을 권장합니다. 

피드백은 언제나 환영입니다. 댓글로 달아주세요 ^-^

 

 

반응형