파이썬 기초 강좌 #7 문자열 다루기

16 분 소요

안녕하세요. 스쿨오브웹의 이상희입니다. 파이썬 기초강좌 일곱번째 강좌인 문자열 다루기를 시작하겠습니다.

문자열이란?

영어로 string 이라고 불리는 문자열은 캐릭터 (character) 의 나열입니다. 문자열은 홀 따옴표나 쌍 따옴표를 사용하여 표시합니다. ex) 'string' or "string" 플러스 (+) 오퍼레이터를 사용하여 문자열과 문자열을 결합할 수 있습니다. ex) 'schoolofweb' + '.net" 실제 코드를 실행하면서 설명을 하겠습니다.

>>> 'string'
'string'
>>> "string"
'string'

문자열 안에 홀 따옴표나 쌍 따옴표를 표시해야 할 경우가 있습니다. 보기와 같은 코드를 실행하면 신텍스 에러가 발생하게 됩니다.

>>> 'I'm a programmer'
File "<stdin>", line 1
'I'm a programmer'
^
SyntaxError: invalid syntax

홀 따옴표를 표시하고 싶을 때는 쌍 따옴표로, 쌍 따옴표를 표시하고 싶을 때는 홀 따옴표로 문자열을 감싸면 됩니다.

>>> "I'm a programmer"
"I'm a programmer"
>>> 'He says "Hello!"'
'He says "Hello!"'

또 다른 방법은 백슬래쉬를 사용하여 특수문자를 일반 문자로 예외 처리를 하는 방법이 있습니다. 위에서 에러가 났던 코드를 수정하여 실행해 보겠습니다.

>>> 'I\\'m a programmer'
"I'm a programmer"

이번에는 에러 없이 잘 출력되는 것을 볼 있습니다.

문자열과 문자열을 결합하고자 할 때는 플러스 오퍼레이터를 사용하시면 됩니다.

>>> 'schoolofweb' + '.' + 'net'
'schoolofweb.net'

하지만 문자열과 숫자를 합치려면 숫자를 먼저 문자열로 변환하여야 합니다. age라는 변수안의 숫자와 문자열을 결합해보겠습니다.

>>> 'I am ' + 18 + ' years old'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

타입 에러가 발생하는것을 볼 수 있습니다.

이번에는 문자열로 변환한 후 결합해 보겠습니다.

>>> 'I am ' + str(18) + ' years old'
'I am 18 years old'

문제없이 결합되는 것을 볼 수 있습니다.

인덱싱이란?

인덱싱이란 브라켓 신텍스와 숫자를 사용하여 문자열안의 특정 위치의 문자를 추출하는 것을 말합니다. 파이썬은 0 부터 시작하는 제로 베이스 인덱싱을 사용합니다. 제로 베이스 인덱스란 인덱스의 시작이 제로 부터 시작하는 시스템입니다. 즉 첫 번째 아이템의 인덱스가 0가 되고 두번째 아이템이 1, 세번째 아이템이 2가 되는것을 말합니다.

인덱스와 리버스 인덱스
인덱스와 리버스 인덱스

위의 이미지와 같이 STRING 이라는 문자열이 있을 때, 첫 번째 문자인 S가 문자열의 첫 번째 아이템이 되고 이 아이템의 인덱스가 0이 되는 것입니다. 오른쪽으로 이동할수록 인덱스가 1씩 증가하게됩니다.

마지막 아이템으로부터 인덱싱을 하는 것을 리버스 인덱싱이라고하고 이때 인덱스는 -1로 부터 시작하여 1씩 감소하게 됩니다.

STRING 이라는 문자열을 변수에 저장한 뒤, 인덱스를 사용하여 첫 번째 문자인 S를 출력해 보겠습니다.

>>> var = 'STRING'
>>> var[0]
'S'

이 번에는 리버스 인덱스를 사용하여 마지막 문자인 "G"를 출력해 보겠습니다.

>>> var[-1]
'G'

이 문자열의 인덱스 레인지는 0 부터 5까지입니다. 하지만 이 레인지를 벗어난 인덱스를 사용하면 인덱스 에러가 발생하게 됩니다.

앞에서 파이썬은 제로 베이스 인덱스를 사용한다고 설명을 드렸는데요, 사실상 C++, Java, JavaScript 등 거의 대부분의 주류 프로그래밍 언어가 제로 베이스 인덱스를 사용하고 있습니다. 하지만 Lua, Julia, R과 같이 언어들은 인덱스가 1로 시작되는 원 베이스 인덱스를 사용하고 있습니다.

이번에는 슬라이싱을 배워보도록 하겠습니다.

슬라이싱이란?

슬라이싱은 인덱스와 같이 브라켓 신텍스를 사용하여 문자열안에서 문자나 문자열을 추출하는 기술입니다. 인덱싱으로는 하나의 문자만을 추출할 수 있지만, 슬라이싱을 사용하면 여러개의 문자를 추출할 수 있습니다.

슬라이싱의 신텍스는 브라켓안에 세가지 숫자를 가집니다. 숫자와 숫자 사이는 콜론으로 구분합니다.

슬라이싱 신텍스

[start:stop:step]

start는 추출하고자 하는 문자열의 첫 캐릭터의 인덱스입니다. stop은 추출하고자 하는 문자열의 마지막 캐릭터의 인덱스에 1을 더한 값입니다. step은 start에서 stop까지의 증가 크기를 뜻합니다. step은 생략이 가능하며, 생략시에는 디폴트 값인 1이 사용됩니다. 만약 보기의 문자열에서 첫 3개의 캐릭터를 추출하고자 하면 [:3] 를 입력하면 됩니다.

>>> var[0:3]
'STR'

이때 start 인덱스가 0이면 생략이 가능합니다.

>>> var[:3]
'STR'

마지막 3개의 캐릭터를 추출하고 싶다면 [-3:] 를 입력하면 됩니다.

>>> var[-3:]
'ING'

중간의 2개 캐릭터를 추출하고 싶다면 [2:4]를 사용하거나 [-4:-2]를 사용하시면 됩니다.

>>> var[2:4]
'RI'
>>> var[-4:-2]
'RI'

이번에는 숫자와 알파벳이 섞인 문자열에서 step 값을 적용하여 알파벳만을 추출해 보겠습니다.

>>> mixed = '1a2b3c'
>>> mixed[1::2]
'abc'

이번에는 스트링 빌트인 클래스가 제공하는 메소드에 대해서 알아보겠습니다.

str의 메소드

lupper: 문자열을 대문자로 변환 lower: 문자열을 소문자로 변환 capitalize: 첫 캐릭터를 대문자로 변환 split: 문자열을 리스트 아이템으로 분리 join: 특정 캐릭터나 문자열로 다른 문자를 연결 strip: White space를 삭제 replace: 특정 캐릭터를 다른 캐릭터로 치환 format: 문자열안의 place holder에 원하는 값을 대체 파이썬안의 모든 것은 어떤 클래스의 오브젝트이며, 클래의안에 정의된 메소드를 사용할 수 있습니다. 스트링 클래스도 여러가지 편리한 메소드를 제공하고 있습니다.

이중에서 일반적으로 많이 사용되는 메소드를 사용해보겠습니다.

먼저 한 문장을 변수에 저장하고, 타입 함수를 사용하여 변수에 저장된 오브젝트의 타입을 알아보겠습니다.

>>> greeting = 'welcome to schoolofweb.net.'
>>> type(greeting)
<class 'str'>

string 오브젝트가 저장된것을 확인하였습니다.

dir 함수를 사용하여 스트링 오브젝트가 어떤 메소드를 사용할 수 있는지 출력해 보겠습니다.

>>> dir(greeting)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

Ipython이나 jupyter notebook을 사용하고 계시다면 탭키를 사용하여 코드 힌트를 볼 수도 있습니다.

스트링 클라스의 메소드
스트링 클라스의 메소드

사용 가능한 메소드가 모두 보이는 것을 알 수 있습니다.

첫 번째 캐릭터를 대문자로 변환해주는 capitalize 메소드를 실행해 보겠습니다.

>>> greeting.capitalize()
'Welcome to schoolofweb.net.'

이번에는 모든 문자열을 대문자로 변환하는 upper 메소드와 모든 문자열을 소문자로 변환하는 lower 메소드를 실행해보겠습니다.

>>> greeting.upper()
'WELCOME TO SCHOOLOFWEB.NET.'
>>> greeting.lower()
'welcome to schoolofweb.net.'

이번에는 특정 문자를 이용하여 문자와 문자를 연결해 주는 join 메소드를 사용해 보겠습니다.

>>> period = '.'
>>> abc = 'ABC'
>>> period.join(abc)
'A.B.C'

ABC 문자열의 각 캐릭터가 피리어드로 연결된 것을 볼 수 있습니다.

이 번에는 양 사이드의 white space를 삭제하는 strip 메소드를 사용해 보겠습니다.

>>> spaces = ' strip example '
>>> spaces.strip()
'strip example'

양 사이드의 white space가 삭제된 것을 볼 수 있습니다.

다음의 문자열을 콤마를 기준으로 하여 스플릿하여보겠습니다.

>>> numbers = 'one,two,three,four,five'
>>> numbers.split(',')
['one', 'two', 'three', 'four', 'five']

콤마를 기준으로 각 단어가 리스트 아이템으로 분리된것을 볼 수 있습니다.

이 번에는 특정 캐릭터나 문자열을 치환하는 replace 메소드를 사용해보겠습니다.

>>> foo = 'this is a java tutorial for java programmers'
>>> foo.replace('java', 'python')
'this is a python tutorial for python programmers'

java 라는 문자열이 python으로 치환된것을 볼 수 있습니다.

String Formatting

빈 컬리 브레이스 사용

'My name is {}. I am {} years old.'.format(name, age)

키워드 사용

'My name is {name}. I am {age} years old.'.format(name=name, age=age)

인덱스 사용

'My name is {1}. I am {0} years old.'.format(age, name)

마지막으로 확인할 메소드는 format 메소드입니다. 포멧 메소드를 사용하면 문자열안에 컬리브레이스로 여러개의 플레이스 홀더를 정의한 뒤 원하는 값으로 다이나믹하게 치환할 수 있습니다. 즉 템플릿을 만들어 사용한다고 생각하시면 됩니다. 포멧 메소드를 사용하려면 문자열 안에 컬리 브레이스를 사용하여 플레이스 홀더를 정의합니다. 이 플레이스 홀더의 사용 방법은 세가지가 있습니다. 첫 번째 방법은 빈 컬리브레이스를 사용하는 방법입니다. 빈 컬리 브레이스를 사용하면 format 메소드에 전달되는 인자가 플레이스 홀더에 순서대로 치환됩니다.

>>> name = 'Pink'
>>> age = 13
>>> 'My dog\\'s name is {}. She is {} years old.'.format(name, age)
"My dog's name is Pink. She is 13 years old."

플레이스 홀더의 숫자와 메소드에 전달되는 인자의 수는 꼭 같아야 하며, 만약 수가 매칭되지 않으면 인덱스 에러가 발생합니다. 이 예와 같이 플레이스 홀더는 2개인데 인자를 하나만 패스하면 인덱스 에러가 발생합니다.

>>> 'My dog\\'s name is {}. She is {} years old.'.format(name)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: Replacement index 1 out of range for positional args tuple

두번째 방법으로는 키워드를 사용하는 방법이 있습니다. 플레이스 홀더가 많고 같은 값을 여러 번 사용하는 경우에는 키워드를 사용하는 것을 권장합니다.

>>> 'My dog\\'s name is {name}. She is {age} years old.'.format(name=name, age=age)
"My dog's name is Pink. She is 13 years old."

세번째 방법은 인덱스를 사용하는 방법입니다. 컬리 브레이안에 format 메소드에 전달 되는 인자의 인덱스를 입력하면 됩니다.

>>> 'My dog\\'s name is {1}. She is {0} years old.'.format(age, name)
"My dog's name is Pink. She is 13 years old."

다음과 같이 숫자 앞에 제로 패딩을 표시할 수도 있습니다.

>>> for i in range(1, 11):
...     print('file_{:03d}'.format(i))
...
file_001
file_002
file_003
file_004
file_005
file_006
file_007
file_008
file_009
file_010

여기서 제로는 빈 공간을 제로 캐릭터로 채우겠다는 뜻이고, 3은 문자열의 최소 길이를 뜻합니다.

포맷 메소드를 사용하여 소수점 자리수를 정의할 수도 있습니다. 소수점을 세자리만 출력하여 보겠습니다.

>>> '{:.3f}'.format(1.55555)
'1.556'

뒤에 소수점을 버리면 반올림 또는 반내림을 하는 것을 기억하시기 바랍니다.

로그 등을 출력할 때 문자 길이를 맞추거나 왼쪽, 중앙, 오른쪽 정렬 등을 하여 보기좋게 포멧팅할 수도 있습니다.

>>> text = ''
>>> text += '{:10s} {:9s} {:4s}\\n'.format('First Name', 'Last Name', 'Age')
>>> text += '{} {} {}\\n'.format('-'*10, '-'*9, '-'*4)
>>> for person in people:
...     text += '{:>10s} {:^9s} {:<4d}\\n'.format(person['firstname'], person['lastname'], person['age'])
...
>>> print(text.strip())
First Name Last Name Age
---------- --------- ----
      John    Doe    30
      Jane    Doe    29
    Curtis    Lee    43

이번 강좌는 여기서 마치고 다음 강좌에서는 리스트에 대해서 알아보겠습니다.