Python

나도코딩 파이썬 4장 - 문자열 다루기

햣둘 2023. 3. 16. 21:58

4.1 문자열이란

문자열이란? 문자들의 집합을 의미한다.

문자열을 여러 줄에 걸쳐 작성할 때에는 여는 따옴표와 닫는 따옴표를 각각 3개씩 넣어 앞뒤로 감싸주면 된다.

그러면 안에 든 모든 글자를 문자열로 인식한다. (큰따옴표와 작은따옴표 둘 다 가능)

sentence = """
오늘은 2023년 3월 16일이에요.
시간은 9시 20분이에요.
"""
print(sentence)

 

4.2 원하는 만큼 문자열 자르기 : 슬라이싱

파이썬에서는 '슬라이싱'(slicing)이라는 방법으로 원하는 만큼 데이터를 자를 수 있다.

슬라이싱을 사용하려면 인덱스(index)를 먼저 알아야 한다.

인덱스는 데이터의 순서 또는 위치를 나타낸다.

인덱스는 데이터를 저장한 변수명에 대괄호[]를 붙이고 그 안에 숫자를 넣어 표시한다.

jumin = "990229-1234567"
print("성별 식별번호 : " + jumin[7]) #1

성별을 나타내는 1이라는 값은 문자열에서 8번째 자리에 있는데 왜 7번째 인덱스라고 적었을까?

코드에서 인덱스는 1이 아닌 0부터 시작하기 때문이다. 중요!!!

 

슬라이싱은 대괄호 안에 인덱스를 넣고 필요한 범위를 콜론(:)으로 구분해 표시한다.

형식 : 변수명[시작 인덱스 : 종료 인덱스]  #시작 인덱스부터 종료 인덱스 직전까지

jumin = "990229-1234567"
print("연 : " + jumin[0:2]) #0부터 2직전까지(0,1)
print("월 : " + jumin[2:4]) #2부터 4직전까지(2,3)
print("일 : " + jumin[4:6]) #4부터 6직전까지(4,5)

'''실행결과
연 : 99
월 : 02
일 : 29 
'''

 

슬라이싱할 때 범위를 나타내는 시작 인덱스나 종료 인덱스를 비워두면, 비워둔 위치에 따라 슬라이싱 범위가 달라진다.

  • 변수명[:종료 인덱스] - 처음부터 종료 인덱스 직전까지 슬라이싱
  • 변수명[시작 인데스:] - 시작 인덱스부터 끝까지 슬라이싱
  • 변수명[ : ] - 처음부터 끝까지 슬라이싱
jumin = "990229-1234567"
print("생년월일 : " + jumin[:6]) #처음부터 6직전까지 
print("주민등록번호 뒷자리 : " + jumin[7:]) #7부터 끝까지

'''실행결과
생년월일 : 990229
주민등록번호 뒷자리 : 1234567
'''

 

앞에서부터가 아니라 뒤에서부터 슬라이싱할 수도 있다.

이때는 음수 인덱스를 사용한다.

단, 양수 인덱스일 때는 0부터 시작하지만, 음수 인덱스일 때는 -1부터 시작한다.

jumin = "990229-1234567"
print("주민등록번호 뒷자리 : " + jumin[-7:]) #뒤에서 7번째 위치부터 끝까지

'''실행결과
주민등록번호 뒷자리 : 1234567
'''

 

1분 퀴즈 - 5번 문항

fruit = "apple"
print(fruit[:]) #처음부터 끝까지 
print(fruit[0:]) #0번 인덱스부터 끝까지
print(fruit[:5]) #5번 인덱스 직전까지 (0번~4번까지)
print(fruit[:-1]) #-1번 인덱스 직전까지 

'''실행결과
apple
apple
apple
appl
'''

주의!! fruit[ :-1]로 작성하면 처음부터 종료 인덱스(-1) 직전까지라는 뜻이므로 appl을 출력한다.

 

4.3 함수로 문자열 처리하기

문자열 처리 함수는 문자열(또는 문자열을 담은 변수)과 함수를 점(.)으로 연결해 사용한다.

형식 : 문자열(또는 변수).함수()

python = "Python is Amazing"

print(python.lower()) # 전체 소문자로 변환
print(python.upper()) # 전체 대문자로 변환
print(python[0].isupper()) # 인덱스 0에 있는 값이 대문자인지 확인
print(python[1:3].islower()) # 인덱스 1부터 2에 있는 값이 소문자인지 확인
print(python.replace("Python", "Java")) # Python을 Java로 바꾸기

''' 실행결과
python is amazing
PYTHON IS AMAZING
True
True
Java is Amazing
'''

 

어떤 문자가 문자열의 어느 위치에 있는지 찾는 함수로 find()와 index()가 있다.

시작 인덱스와 종료 인덱스 사이에서 지정한 문자를 찾는데, 시작 인덱스와 종료 인덱스는 생략 가능하다.

시작 인덱스와 종료 인덱스를 모두 생략하면 문자열 전체에서 찾고, 종료 인덱스만 생략하면 시작 인덱스부터 문자열 끝까지 확인한다.

 

두 함수의 차이점은 찾는 문자가 문자열 안에 없는 경우에 나타난다.

찾는 문자가 문자열 안에 없을 때 find()함수 -1을 반환하고 다음 문장을 실행한다.

반면 index()함수오류(ValueError : substring not found, 문자열을 발견하지 못함)가 발생하면서 이후 문장을 수행하지 않고 프로그램을 종료한다.

 

python = "Python is Amazing"

find = python.find("n") # 처음 발견한 n의 인덱스
print(find) #'Python'에서 n(인덱스 5)
find = python.find("n", find + 1) #인덱스 6 이후부터 찾아 처음 발견한 n의 인덱스
print(find) # 'is Amazing'에서 n(인덱스 15)
find = python.find("Java") #Java가 없으면 -1을 반환한 후 프로그램 계속 수행
print(find) # -1 반환

'''실행결과
5
15
-1
'''

먼저 python.find("n")을 하면 문자열에서 처음으로 발견하는 n(알파벳 'n')의 위치인 5를 얻어와 find 변수에 저장한다.

그런 다음 python.find("n", find + 1)을 하면 문자열에서 n을 찾는데 찾기 시작하는 위치가 인덱스 6부터라는 뜻이다.

그래서 'Python is Amazing'이라는 문자열에서 n을 찾을 때 P부터가 아니라 인덱스 6에 있는 is 바로 앞의 공백부터 찾게 된다. 그래서 공백 앞에는 n이 있거나 말거나 그냥 무시하고 지나간다. 따라서 결과로 15가 된다. 

슬라이싱을 할 때 a[6:]을 하면 인덱스 6부터 끝까지 문자열을 잘라서 가져오는 것과 비슷하다.

 

python = "Python is Amazing"

index = python.index("n") # 처음 발견한 n의 인덱스
print(index) #'Python'에서 n(인덱스 5)
index = python.index("n", index + 1) #인덱스 6 이후부터 찾아 처음 발견한 n의 인덱스
print(index) # 'is Amazing'에서 n(인덱스 15)
index = python.index("Java") #Java가 없으면 오류가 발생하며 프로그램 종료
print(index) # 오류

'''실행결과
5
15
ValueError: substring not found
'''

index()함수를 사용해도 대부분의 결과는 같다.

단 python.find("Java")와 python.index("Java")는 다르다.

python.find("Java")에서는 문자열 Java가 없으므로 -1을 출력하고 다음 코드로 넘어간다.

하지만 python.index("Java")에서는 문자열에 Java가 없어서 오류를 출력하고 프로그램을 종료한다.

 

count()함수지정한 문자 또는 문자열이 총 몇 번 나오는지 횟수를 확인할 수 있다.

만약 해당 문자나 문자열이 없다면 0으로 표시한다.

python = "Python is Amazing"

print(python.count("n")) #2
print(python.count("v")) #0

 

len()함수는 문자열의 길이 정보를 알려주는데, 이때 문자열 길이에는 공백까지 모두 포함한다.

python = "Python is Amazing"

print(len(python)) #17

주의 !! python 자체의 길이가 아니라 python 변수 내의 문자열의 길이를 반환

 

4.4 문자열 포매팅

문자열과 다른 자료형을 연결하려면 형변환을 해야한다.

그런데 형변환 없이 문자열과 다른 자료형을 연결하는 방법이 있다.

원하는 위치에 특정한 값(또는 변수)을 넣어서 하나의 문자열로 표현하는 방법으로, '문자열 포매팅'이라고 한다.

 

4.4.1 서식 지정자 사용하기

첫 번째 방법은 서식 지정자를 사용하는 것이다.

서식 지정자는 자료형을 표현하는 방법으로, % 뒤에 자료형을 나타내는 문자가 붙는다.

형식 : print("문자열 서식지정자 문자열" % 값)

서식 지정자 의미
%d 정수(decimal)
%f 실수(floating-point)
%c 문자(character)
%s 문자열(string)

 

문자열과 다른 값을 연결하고 싶은 위치에 값의 자료형에 해당하는 서식 지정자를 넣는다.

그리고 문자열 다음에 %를 적고 한 칸 띄어서 값을 넣으면 이 값이 문자열 중간에 있는 서식 지정자 위치에 들어가서 출력된다. 이때 서식 지정자 중에서 %s를 사용하면 정수, 문자, 문자열 등과 상관없이 모든 값을 넣을 수 있다.

print("나는 %d살입니다." % 23)
print("나는 %s를 좋아합니다." % "고양이")
print("Apple은 %c로 시작해요." % "A")
print("나는 %s살입니다." % 20) # %s를 사용하면 정수, 문자, 문자열 등과 상관없이 모든 값을 넣을 수 있음

'''실행결과
나는 23살입니다.
나는 고양이를 좋아합니다.
Apple은 A로 시작해요.
나는 20살입니다.
'''

 

문자열 안에 값을 2개 이상 넣고 싶다면 원하는 위치에 서식 지정자를 원하는 만큼 넣는다.

그리고 문자열에 넣을 값들을 쉼표로 구분한 후 소괄호로 감싸서 % 뒤에 넣는다.

그러면 값이 순서대로 문자열의 서식 지정자 위치에 들어간다.

print("나는 %s와 %s를 좋아해요." % ("고양이", "강아지"))
# 실행결과 : 나는 고양이와 강아지를 좋아해요.
# 값이 여러 개일 때 서식 지정자 사용하는 방법

 

 

4.4.2 format()함수 사용하기

두 번째는 format() 함수를 다음과 같은 형식으로 사용하는 방법이다.

형식 : print("문자열{인덱스}문자열{인덱스}...".format(값1, 값2, ...))

문자열에서 값을 넣을 위치에 중괄호{} 표시를 하고 뒤에 format(값1, 값2, ...) 형태로 값을 입력한다.

그리고 점(.)으로 문자열과 format()함수를 연결하면 -> 값들이 문자열의 중괄호 부분에 들어간다.

print("나는 {}살입니다." .format(23))
print("나는 {}색과 {}색을 좋아해요." .format("파란", "빨간"))
print("나는 {0}색과 {1}색을 좋아해요." .format("파란", "빨간"))
print("나는 {1}색과 {0}색을 좋아해요." .format("파란", "빨간"))

'''실행결과
나는 23살입니다.
나는 파란색과 빨간색을 좋아해요.
나는 파란색과 빨간색을 좋아해요.
나는 빨간색과 파란색을 좋아해요.
'''

문자열에 비어있는 중괄호만 표시하면 값이 순서대로 들어가고,

{0}, {1} 처럼 인덱스를 넣으면 인덱스에 맞춰 {0} 위치에는 값1, {1} 위치에는 값2가 들어간다.

그래서 {1}, {0}처럼 순서를 뒤집어서 넣으면 값도 순서가 바뀌어서 나오게 된다.

 

* 참고! 실행했을 때 'SyntaxError : invalid syntax'와 같은 오류 메시지가 나온다면 예제 코드 바로 윗문장에서 닫는 괄호)가 누락됐는지 확인해 볼 것. format()함수 사용할 때 닫는 괄호 1개만 작성하는 실수가 잦으니 여는 괄호와 닫는 괄호의 개수가 같은지 꼭 확인해야 한다.

 

중괄호 안에 이름을 넣을 수도 있다.

형식 : print("문자열{이름1}문자열{이름2}..." .format(이름1=값1, 이름2=값2, ...))

중괄호에 이름을 넣고 format()함수에 이름과 값을 정의하면 중괄호 위치에 이름에 해당하는 값이 들어가게 된다.

print("나는 {age}살이고 {color}색을 좋아해요." .format(age=23, color="빨간")) 
print("나는 {age}살이고 {color}색을 좋아해요." .format(color="빨간", age=23)) 
      
'''실행결과
나는 23살이고 빨간색을 좋아해요.
나는 23살이고 빨간색을 좋아해요.
'''

값을 이름으로 직접 지정하기 때문에 중괄호와 format()함수에서 이름 순서가 달라져도 상관 없다.

 

 

4.4.3 f-문자열 사용하기

마지막은 f-문자열을 사용하는 방법이다.

문자열 앞에 f를 추가하면 문자열이 나오기 전에 정의한 변수의 값을 문자열에서 사용할 수 있다.

(단, 이 방법은 파이썬 3.6버전 이상일 때만 사용 가능)

 

형식 : print(f"문자열{변수명1}문자열{변수명2}...")

age = 23
color = "연두"
print(f"나는 {age}살이며, {color}색을 좋아해요.")
#실행결과 : 나는 23살이며, 연두색을 좋아해요.

코드를 보면 age와 color라는 변수를 정의한다. 

그러고 나서 print()문에서 변수명을 중괄호로 감싸 문자열 안에 넣으면 정의한 변수의 값을 중괄호 위치에 넣어 문자열과 함께 출력한다.

 

4.5 탈출 문자

탈출 문자는 \와 특정 문자를 함께 사용해 문장 안에서 원하는 동작을 수행하는 방법이다.

 

4.5.1 \n

코드에서 \n은 문자열 안에서 줄바꿈을 할 때 사용하는 탈출문자이다.

그래서 \n 뒷부분은 다음 줄에 출력된다.

print("백문이 불여일견 \n백견이 불여일타")

'''실행결과
백문이 불여일견
백견이 불여일타
'''

 

 

4.5.2 \"와 \'

탈출 문자 \"와 \'를 사용하면 문자열 안에서도 따옴표를 마음껏 사용할 수 있다.

print("저는 \"나도코딩\"입니다.")
print("저는 \'나도코딩\'입니다.")

'''
저는 "나도코딩"입니다.
저는 '나도코딩'입니다.
'''

 

 

4.5.3 \\

탈출 문자는 다른 경우에도 필요하다. 

C:\Users\Nadocoding\Desktop\PythonWorkspace 처럼 어떤 폴더나 파일의 전체 경로를 그대로 출력하면?

SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

이렇게 오류가 발생한다. 코드를 가만히 보면 \U, \N, \D, \P와 같이 탈출 문자의 형태를 띈 곳이 보인다. 이와 같이 유효하지 않은(실제 없는) 탈출 문자를 포함하면 오류가 난다. 또는 경로 안에 \n과 같이 유효한 형태의 탈출 문자가 있으면 실제로 출력하고자 하는 값과는 다르게 두 줄로 출력되는 등의 상황이 발생할 수도 있다.

 

이때는 백슬래시 2개를 사용하면 제대로 출력된다.

print("C:\\Users\\Nadocoding\\Desktop\\PythonWorkspace")
#실행결과 C:\Users\Nadocoding\Desktop\PythonWorkspace

 

문자열 앞에 r을 붙이는 방법도 있다.

r을 추가하면 문자열 내에 어떤 값이 있든지 무시하고 그대로 출력한다.

print(r"C:\Users\Nadocoding\Desktop\PythonWorkspace")
#실행결과 C:\Users\Nadocoding\Desktop\PythonWorkspace

 

 

4.5.4 \r

잘 쓰이진 않지만, 탈출 문자 중에는 \r, \b, \t도 있다.

먼저 \r은 커서를 맨 앞으로 이동시킨다.

print("Red Apple\rPine")
# PineApple

이와 같은 문장이 있을 때 Red Apple을 출력한 후 \r을 만나면 커서를 맨 앞, 즉 Red 앞으로 이동시킨다. 

그리고 해당 위치에서 \r 다음에 오는 Pine을 출력한다. 이는 마치 Red를 덮어쓰는 효과를 낸다. 

따라서 실행결과는 PineApple이 된다.

 

 

4.5.5 \b

\b는 키보드에서 백스페이스와 같은 역할을 한다. 

즉, 앞 글자 하나를 삭제한다.

print("Redd\bApple")
# RedApple

위의 코드를 실행하면 Redd 중 마지막 d를 없애고 출력한다.

 

 

4.5.6 \t

마지막으로 보는 \t는 키보드의 Tab과 같이 여러 칸을 띄어 쓰는 역할을 한다.

print("Red\tApple")
# Red     Apple

실행 결과가 표시되는 터미널에서는 8칸이 기준이다. 8칸은 글자와 글자 사이 간격이 아니라 첫번째 글자로부터 8칸이다. 따라서 Red의 R부터 8칸 떨어진 곳에 Apple을 출력한다.

 

 

4.6 실습문제 : 비밀번호 만들기

사이트별로 비밀번호 생성하는 프로그램 작성하기

<조건>

1. http:// 부분은 제외

2. 처음 만나는 점(.) 이후 부분도 제외

3. 남은 글자 중 처음 세 자리 + 글자 개수 + 글자 내 'e'의 개수 + '!'로 구성 

url = "http://naver.com"
# url = "http://daum.net"
# url = "http://google.com"
# url = "http://youtube.com"

my_str = url.replace("http://", "")
# 조건1에 해당. http:// 부분 제외

my_str = my_str[:my_str.index(".")] 
# 조건2에 해당. 처음 만나는 점(.) 이후 부분도 제외

password = my_str[:3] + str(len(my_str)) + str(my_str.count("e")) + "!"
# 비밀번호 = 처음 세자리 + 글자 개수 + 글자 내 'e'의 개수 + '!'

print("{0}의 비밀번호는 {1}입니다." .format(url, password))
'''실행결과
http://naver.com의 비밀번호는 nav51!입니다.
http://daum.net의 비밀번호는 dau40!입니다.
http://google.com의 비밀번호는 goo61!입니다.
http://youtube.com의 비밀번호는 you71!입니다.
'''