문자열

문자열은 리터럴 문자열에서 살펴본 바와 같이 작은 따옴표, 큰 따옴표로 둘러싸면 문자열이 됩니다. 또는 str(x) 함수를 이용해서 문자열을 만들 수 있습니다. str(x)x 객체의 __str()__함수가 구현되어 있으면 x.__str()__값이 반환되고 그렇지 않으면 repr(x)값이 반환됩니다.

In [1]: 문자열 = str(123.12)
   ...: type(문자열)
   ...: 
Out[1]: str

문자열 접근

문자열수집형 의 일종이기 때문에 문자열에 있는 하나 하나의 문자들을 인덱스를 통해 접근할 수 있습니다. 파이썬에서 인덱스란 열거형 안에 있는 항목들의 순서를 나타내는 0부터 시작하는 양의 정수를 말합니다.

문자열 = "문자열은 열거형이라서 인덱스를 통해서 성분들을 접근할 수 있습니다."

print("인덱스 0인 문자:", 문자열[0])
인덱스 0 문자: 

열거형은 슬라이싱도 가능합니다. 즉, 원하는 부분만 추려낼 수 있습니다.

문자열 = "문자열은 열거형이라서 인덱스를 통해서 성분들을 접근할 수 있습니다."

print("0부터 10까지 성분들:", 문자열[0:11])
0부터 10까지 성분들: 문자열은 열거형이라서

열거형의 성분들의 갯수를 알 수 있는 len() 함수를 이용할 수 있습니다.

문자열 = "문자열 성분의 갯수를 알수 있습니다."

len(문자열)
18

문자열의 마지막 문자를 알아보기 위해서 다음과 같이 문자열의 크기로 접근하면 에러가 납니다.

문자열 = "문자열 성분의 갯수를 알수 있습니다!"
문자열크기 = len(문자열)
문자열[문자열크기]
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-71-db68cc434fbd> in <module>()
      1 문자열 = "문자열 성분의 갯수를 알수 있습니다!"
      2 문자열크기 = len(문자열)
----> 3 문자열[문자열크기]


IndexError: string index out of range

왜냐하면 문자열의 인덱스는 0부터 시작하기 때문에 문자열의 마지막 인덱스는 len(문자열)-1이 됩니다.

문자열 = "문자열 성분의 갯수를 알수 있습니다!"
문자열크기 = len(문자열)
문자열[문자열크기 - 1]
'!'

+ 연산자를 이용해서 2개의 문자열을 붙일 수 있습니다.

"앞 문자열" + "뒷 문자열"
'앞 문자열뒷 문자열'

그런데 숫자와 문자열을 붙일려고 + 연산자를 사용하면 다음과 같은 에러가 납니다.

"문자열" + 100
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-74-a8d3652033c4> in <module>()
----> 1 "문자열" + 100


TypeError: must be str, not int

100은 숫자형이라서 문자열과 + 덧셈이 정의되지 않아서 에러를 내는 것입니다. 이럴때는 숫자형을 문자형으로 변형하는 str() 메소드를 사용하면됩니다.

"문자열" + str(100)
'문자열100'

비교 연산

비교 연산자 <, >, ==를 이용하여 두 문자열을 비교할 수 있습니다. 두 문자열은 사전식 배열의 순서를 가지고 앞, 뒤를 비교합니다. 문자열은 사전식 배열에서 뒤에 있을 수록 커진다.

"나는" < "너는"
True
단어 = "한글"

if 단어 == "한글":
    print(단어+"을 사랑합시다.")
한글을 사랑합시다.

모든 영문 대문자는 소문자보다 앞에 있습니다.

'Z' < 'a'
True

innot in 연산

문자열 안에 부분 문자열이 있는지를 확인할 수 있는 연산자 in 또는 not in을 사용할 수 있습니다.

"사" in "사과"
True
"소" in "사과"
False
"붕어" in "붕어빵에 붕어가 있습니다?"
True
"호두알" not in "호두과자"
True

for문 이용 문자열 순회

 = "윤김이정강박"
이름 = "예은"

for 문자 in :
    print(문자+이름)
윤예은
김예은
이예은
정예은
강예은
박예은

불변(immutable)

문자열은 불변이라서 한 번 만들어진 문자열 객체의 내용을 변경할 수 없습니다. 아래와 같이 문자열의 일부를 변경하려고 하면 에러를 발생시킨다.

문자열 = "문자열의 내용은 변경할 수 없습니다."

문자열[0] = '글'
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-84-b66cd0a0738b> in <module>()
      1 문자열 = "문자열의 내용은 변경할 수 없습니다."
      2
----> 3 문자열[0] = '글'


TypeError: 'str' object does not support item assignment

그렇지만 새로운 객체를 기존의 변수에 대입하는 것은 아무 문제가 되질 않습니다.

문자열 = "문자열의 내용은 변경할 수 없습니다."

문자열 = "새로운 문자열 객체를 대입합니다."

print(문자열)
새로운 문자열 객체를 대입합니다.

format

형식 문자열(format string)에 대해서 format() 메소드를 사용할 수 있습니다. 형식 문자열이란 중괄호 { }를 포함하는 문자열을 말합니다. 형식 문자열은 중괄호 기호를 제외한 모든 문자열을 리터럴 문자열로 간주합니다. 형식 문자열 안에 중괄호를 표시하려면 중괄호를 두 번 {{ 또는 }}를 사용하면 됩니다.

 = "format 메소드에서는 중괄호 {}를 제외한 모든 문자열은 리터럴 문자열로 간주합니다!. 중괄호를 표시하고 싶으면 {{ 와 같이 두 번 }} 쓴다."

.format("(이곳이 중괄호가 있던 곳입니다)")
'format 메소드에서는 중괄호 (이곳이 중괄호가 있던 곳입니다)를 제외한 모든 문자열은 리터럴 문자열로 간주합니다!. 중괄호를 표시하고 싶으면 { 와 같이 두 번 } 쓴다.'

변수 에 대입되는 문자열 안에 중괄호가 포함되어 있기 때문에 형식 문자열이 됩니다. 형식 문자열 안의 중괄호에는 format(인자) 메소드에 인자를 넣어서 중괄호를 대체할 수 있습니다. 여기서는 "(이곳이 중괄호가 있던 곳입니다)" 문자열 인자를 넣었습니다. 중괄호 안에 공백 문자가 있으면 format() 메소드 사용시 다음과 같은 에러가 나므로 중괄호 안에는 형식에 맞도록 사용해야 합니다.

"중괄호 { } 안에 공백 문자가 있으면 에러가 납니다".format("에러") # 중괄호 사이에 공백문자(스페이스)가 있어 에러
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-87-6cc1067c8bc1> in <module>()
----> 1 "중괄호 { } 안에 공백 문자가 있으면 에러가 납니다".format("에러") # 중괄호 사이에 공백문자(스페이스)가 있어 에러


KeyError: ' '

예제

예제를 통해서 익혀보자. 중괄호 안에 인자의 순서에 해당하는 인덱스를 넣어서 원하는 위치에 인자값을 표시할 수 있습니다.

"{0}번째, {1}번째, {2}번째".format("첫", "두", 3)
'첫번째, 두번째, 3번째'

인자의 인덱스를 바꾸어 출력되는 값을 변경할 수 있습니다.

"순서를 바꿀 수 있습니다. {1}번째, {2}번째, {0}번째".format("첫", "두", 3)
'순서를 바꿀 수 있습니다. 두번째, 3번째, 첫번째'

중괄호 안을 비워두면 인자가 순서대로 대입됩니다. 중괄호 안에 인덱스가 부분적으로 들어가면 에러가 납니다. 인자의 인덱스는 모두 들어가든지 아니면 모두 비워 두어야 합니다. 단 키워드 인자의 이름은 어느 곳에 위치해도 상관없습니다.

"{}번째, {}번째, {}번째".format("첫", "두", 3)
'첫번째, 두번째, 3번째'

함수 단원에서 배웠던 * 연산자를 통해서 리스트 또는 튜플을 인자에서 풀어서 사용할 수 있습니다.

풀리는인자 = ("첫", "두", "3")

"{}번째, {}번째, {}번째".format(*풀리는인자)
'첫번째, 두번째, 3번째'

인자의 인덱스를 중복해서 사용할 수 있고 사용하지 않아되 됩니다.

"{0}번째, {2}번째, {0}번째".format("첫", "두", 3)
'첫번째, 3번째, 첫번째'

format() 메소드 인자로 키워드 인자가 들어갈 수 있습니다. 키워드 인자의 이름 중괄호 안에 대입하여 원하는 결과를 만들어 냅니다.

"우리가 사용하는 {언어}{만든이}과 여러 학자들이 만들었습니다.".format(언어="한글", 만든이="세종대왕")
'우리가 사용하는 한글은 세종대왕과 여러 학자들이 만들었습니다.'

객체의 속성을 표시할 수 있습니다. 복소수는 실수부분과 허수부분의 속성을 갖고 있습니다. 이 속성을 키워드와 인덱스를 이용하여 접근하여 표시할 수 있습니다.

복소수 = 2 - 5j

print("복소수의 실수부분은 {수.real}이고 허수부분은 {수.imag}입니다.".format(=복소수)) # 키워드 이용
print("복소수의 실수부분은 {0.real}이고 허수부분은 {0.imag}입니다.".format(복소수)) # 인덱스 이용
복소수의 실수부분은 2.0이고 허수부분은 -5.0입니다.
복소수의 실수부분은 2.0이고 허수부분은 -5.0입니다.

중괄호 안에 콜론 : 뒤에 삽입될 문자열에 대한 세부 형식을 지정할 수 있습니다. 즉 {인자이름:형식} 과 같이 사용할 수있습니다. 형식은 다음과 같습니다.

[[채울문자]정렬기호][부호][#][0][길이][그룹옵션][.소숫점길이][타입]

길이란 출력될 문자열의 크기입니다. 채울문자는 문자열이 삽입되고 지정된 길이의 남는 공간을 채울 문자입니다. 정렬기호란 삽입될 문자열이 배치될 위치를 나타내는 문자입니다.

정렬기호

의미

<

삽입될 문자열을 왼쪽에 위치

>

삽입될 문자열을 오른쪽에 위치

^

삽입될 문자열을 가운데 위치

 = "삽입 문자열"

print("{:#^20}".format())
#######삽입 문자열#######

채울문자를 지정했으면 반드시 정렬기호가 함께 입력되어야 합니다.

 = "삽입 문자열"

print("{:*20}".format())
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-96-1227b77267ec> in <module>()
      1  = "삽입 문자열"
      2
----> 3 print("{:*20}".format())


ValueError: Invalid format specifier

채울 문자 *이 있는데 뒤에 정렬 기호가 없기 때문에 오류가 발생합니다.

부호는 삽입될 인자가 숫자일 때 사용하는 것으로 +, -, 스페이스(공백)가 입력가능합니다.

부호 옵션

의미

+

양수, 음수 모두 부호 표시

-

음수일 때만 부호 표시

스페이스

양수일 때는 부호가 스페이스(공백)이고 음수일 때는 - 기호 표시

print("{:#^+10}".format(1.234))
print("{:#^ 10}".format(1.234))
##+1.234##
## 1.234##

# 문자는 삽입 인자가 숫자형일 때 사용되는 것으로 타입에 따라서 이진법은 0b, 8진법은 0o, 16진법은 0x가 숫자 앞에 표시됩니다.

print("정수: {0:#d}, 2진수: {0:#b}, 8진수: {0:#o}, 16진수: {0:#x}".format(23))
정수: 23, 2진수: 0b10111, 8진수: 0o27, 16진수: 0x17

더 자세한 형식 문자열은 https://docs.python.org/3/library/string.html#formatstrings 을 참조하자.

replace

replace(찾을, 바뀔) 찾을 문자열을 바뀔 문자열로 모두 바꾸어 새로운 문자열을 반환합니다.

문자열 = "아찔아찔 현기증이 납니다."
새문자열 = 문자열.replace("아", "어")
print("새문자열:", 새문자열)
새문자열: 어찔어찔 현기증이 납니다.

startswith, endswith

startswith(시작문자열) 시작문자열로 시작하면 True를 반환하고 그렇지 않으면 False를 반환합니다. 마찬가지로 endswith(끝나는문자열) 끝나는문자열로 끝나면 True 그렇지 않으면 False를 반환합니다.

문자열 = "반짝 반짝 작은 별"
print(문자열.startswith("반짝"))
print(문자열.endswith("별"))
print(문자열.startswith("번쩍"))
print(문자열.endswith("벌"))
print(문자열.startswith(("번쩍", "반짝"))) # 문자열 튜플이 올 수 있습니다.
True
True
False
False
True

count

count(찾을문자열) 찾을문자열의 갯수를 반환합니다.

문자열 = "반짝 반짝 작은 별"
문자열.count("반짝")
2

find

문자열.find(찾을문자열) 문자열 안에 찾을문자열이 처음으로 발견되는 인덱스를 반환합니다. 찾는 문자열이 없으면 -1을 반환합니다.

문자열 = "반짝 반짝 작은 별"
문자열.find("짝")
1

참고: 문자열 안에 찾을 문자열이 있는 지 없는 지를 알고 싶으면 in을 사용합니다.

문자열 = "반짝 반짝 작은 별"
"짝" in 문자열
True

split

문자열 메소드 중에서 많이 사용되는 메소드 중의 하나가 split입니다. 여러 단어로 이루어진 문자열을 여백을 기준으로 단어들을 분리해서 리스트를 만들어 반환합니다. 리스트를 만들어 반환할 때 여백은 포함시키지 않습니다. 여백(whitespace)이란 탭(tab), 새 줄(new line), 공백(space) 문자들을 의미합니다.

문자열 = "너의 마음은 나의 마음\n 나의 마음은 너의 마음"
문자열.split()
['너의', '마음은', '나의', '마음', '나의', '마음은', '너의', '마음']

문자열.split(구분문자열)을 이용하면 구분문자열을 기준으로 문자열을 분리합니다.

문자열 = "너의 마음은 나의 마음 나의 마음은 너의 마음"
문자열.split("의")
['너', ' 마음은 나', ' 마음 나', ' 마음은 너', ' 마음']

구분 문자열이 연속이 될 때는 빈 문자로 분리됩니다.

"1,,2,3".split(',')
['1', '', '2', '3']

낱 글자로 분리하려면 list()를 이용합니다.

문자열 = "너의 마음은 나의 마음"
list(문자열)
['너', '의', ' ', '마', '음', '은', ' ', '나', '의', ' ', '마', '음']

직접하기

  • input() 함수를 이용해서 여러 개의 숫자를 한꺼번에 입력받아 모두 더한 값을 출력하는 프로그램을 작성하시오.

join

문자열.join(반복가능객체)반복가능객체의 각 성분 사이를 문자열로 연결합니다.

전화번호 = "010 1234 5678"
번호리스트 = 전화번호.split()
print("번호리스트:", 번호리스트)
번호 = "-".join(번호리스트)
print("연결된 번호:", 번호)
번호리스트: ['010', '1234', '5678']
연결된 번호: 010-1234-5678

반복가능 객체의 요소는 문자열이어야 합니다. 다음 리스트는 반복가능한 객체이지만 요소들이 튜플이므로 에러를 발생합니다.

반복가능 = [("ㄱ", "ㄴ"), ("ㄷ", "ㄹ")]
"-".join(반복가능)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-109-d0a56bbe4d5e> in <module>()
      1 반복가능 = [("ㄱ", "ㄴ"), ("ㄷ", "ㄹ")]
----> 2 "-".join(반복가능)


TypeError: sequence item 0: expected str instance, tuple found

더 많은 메소드들

help() 함수 및 dir() 함수를 이용하면 파이썬 객체들의 도움말을 볼 수 있습니다.

In [2]: help(str)
Help on class str in module builtins:
class str(object)
 |  str(object='') -> str
 |  str(bytes_or_buffer[, encoding[, errors]]) -> str
 |
 |  Create a new string object from the given object. If encoding or
 |  errors is specified, then the object must expose a data buffer
 |  that will be decoded using the given encoding and error handler.
 |  Otherwise, returns the result of object.__str__() (if defined)
 |  or repr(object).
 |  encoding defaults to sys.getdefaultencoding().
 |  errors defaults to 'strict'.
 |
 |  Methods defined here:
 |
 |  __add__(self, value, /)
 |      Return self+value.

strlower 메소드에 대해서 알아볼 수 있습니다.

In [3]: help(str.lower)
Help on method_descriptor:

lower(self, /)
    Return a copy of the string converted to lowercase.

dir() 함수를 이용하면 객체의 속성들을 볼 수 있습니다. 다음은 str 객체의 속성들을 일부분 보여준 것입니다.

In [4]: dir(str)
Out[4]: 
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',

직접하기

  • 문자열 '010*1234****5678''010-1234-5678'로 바꾸는 프로그램을 작성하시오.

문자열에 대해서 더 세밀한 작업을 하려면 정규 표현식(regular expression) 모듈 re을 살펴보면 됩니다.

연습문제

  • 사용자로부터 input() 함수를 이용하여 숫자 5개를 쉼표로 구분해서 입력을 받아 split()을 이용하여 리스트로 만들어 각각의 수를 출력하시오.

  • 사용자로부터 문자열을 입력받아 그 문자열 안에 “는”이라는 문자가 포함된 단어와 단어의 갯수를 출력하는 프로그램을 작성하시오.

  • 문자열 "너의 마음은 나의 마음 나의 마음은 너의 마음"에서 "너""나""나""너"로 바꾸는 프로그램을 작성하시오.

  • 사용자로부터 휴대폰 전화번호를 입력받고 유효한 번호인지를 확인하는 함수 전화번호확인(문자열)를 작성하시오. 유효하면 입력한 번호를 xxx-xxxx-xxxx 형식으로 출력하시오. 입력 받는 문자 중에 -는 유효한 것으로 받아들이도록 합니다. 아래 그림과 같은 결과가 나오도록 하시오.

  • 새로운 암호를 만들 때 숫자, 문자, 특수문자가 반드시 한 문자 이상씩 포함되어야 하고 문자의 갯수는 적어도 8자 이상이어야 합니다. 사용자가 문자열을 입력했을 때 암호 조건에 맞는지 확인하는 프로그램을 작성하시오. 공백문자는 포함하면 안됩니다. 특수문자는 다음을 사용합니다.

'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

포멧(format) 함수

문자열을 생성하려고 할 때, 종종 다른 정보들을 포함하여 생성하고 싶을 때가 있습니다. 이럴 때 format() 함수를 이용해서 문자열을 편리하게 다룰 수 있습니다.

age = 20
name = '홍길동'
print('{0}의 나이는 {1}살 입니다.'.format(name, age))
print('{0}은 파이썬 프로그래밍을 좋아합니다.'.format(name))

괄호 { } 안의 숫자는 format()에 있는 인수의 인덱스를 나타냅니다. 인덱스는 0부터 시작합니다. { } 안의 숫자가 없으면 인자의 순서대로 들어가게 됩니다. 중괄호 {}를 포함하는 문자열을 형식 문자열(formatted string)이라고 합니다. 형식 문자열은 데이터 형 부분에서 자세히 다룬다.

age = 20
name = '홍길동'
print('{}의 나이는 {}살 입니다.'.format(name, age))
print('{}은 파이썬 프로그래밍을 좋아합니다.'.format(name))

괄호 {}안에 공백이 있으면 안됩니다. 표시되는 형식을 더 세밀하게 조정할 수 있습니다.

# 소수점 3자리까지 표시
print('{0:.3f}'.format(1.0/3))
# 밑줄 문자 '_' 로 11칸을 채우고, 그 중간에 'hello' 문자열을 놓습니다.
# (^) 은 문자열을 중앙에 위치시키고 (>)은 오른쪽, (<)은 왼쪽에 위치시킨다.
print('{0:_^11}'.format('hello'))
# 변수를 이용해서 표시할 수 있습니다.
print('{name}{book} 책을 만들고 있습니다.'.format(name='윤대기', book='"파이썬 한 입"'))
0.333
___hello___
윤대기는 "파이썬 한 입" 책을 만들고 있습니다.

형식문자열 리터럴

형식문자열 리터럴은 문자열 앞에 f 또는 F를 붙이고 표현식 expression 로 작성하여 문자열에 파이썬 표현식의 값을 삽입할 수 있게 만든 문자열입니다. 선택적인 포맷 지정자가 표현식 뒤에 올 수 있습니다. 이것으로 값이 포맷되는 방식을 더 정교하게 제어할 수 있습니다. 다음 예는 원주율을 소수점 이하 세 자리로 반올림합니다.

탈출 문자열(escape sequence)

'What's your name?'과 같이 작은 따옴표 '로 만들어진 문자열 안에 작은 따옴표가 있으면 문자열이 어디서 끝나는지를 명확하게 알 수 없게 되므로 에러를 냅니다.

'What's your name'
  File "<ipython-input-14-d10fcea8627e>", line 1
    'What's your name'
          ^
SyntaxError: invalid syntax

이 때는 "What's your name?"과 같이 큰 따옴표를 사용해도 되지만 탈출 문자 역슬래시 \를 이용해서 작은 따옴표를 사용하면서도 문자열 안에 작은 따옴표 '를 넣을 수 있습니다. 즉, \'와 같이 작은 따옴표 앞에 역슬래시 \를 붙임으로 작은 따옴표를 문자열을 만드는 문자가 아니라고 인식하게 합니다. 마찬가지 방법으로 탈출문자와 큰 따옴표를 사용함으로 큰 따옴표를 문자열에 포함시킬 수 있습니다.

'What\'s your name'
"What's your name"

역슬래시 자체를 문자열에 포함시키려면 역슬래시를 두 번 \\ 사용하면됩니다. \n 문자열(new line)을 이용하면 이 문자열이 위치한 곳에서 엔터를 치는 효과를 얻을 수 있습니다. 즉 \n 뒷부분부터 새로운 줄에 표시되게 합니다.

print("첫번째 줄입니다.\n여기부터는 두번째 줄입니다.")
첫번째 줄입니다.
여기부터는 두번째 줄입니다.

\t 문자열을 이용하면 키보드에서 탭(Tab) 키를 누른 효과를 낼 수 있습니다.

print("하나\t\t셋")
하나         

문자열에 대한 자세한 사용법은 앞으로 나올 클래스 부분에서 다루게 될 것입니다.