안녕하세요! Hak2입니다.
이번에는 문자열에서 심화된 내용을 정리해보겠습니다. 심화된 내용이라 내용이 긴 점 양해 부탁드립니다.🐏🌞
1. 리스트와 튜플의 응용
파이썬에서의 리스트(list)는 요소를 추가, 삭제하거나, 정보를 조회하는 메서드(함수)를 제공해줍니다. for반복문과 결합하여 연속적이고 반복되는 값을 손쉽게 처리 가능한데 리스트를 조작하는 메서드(method) 때문입니다.
메서드는 객체에 속한 함수라는 뜻을 가지고 있습니다.
먼저, 리스트에 요소를 추가해보겠습니다. 요소를 추가하는 메서드 중 자주 사용되는 메서드는 아래와 같습니다.
append : 요소 하나를 추가
extend : 리스트를 연결하여 확장
insert : 특정 인덱스에 요소 추가
순서대로 예제를 보겠습니다. 메서드를 호출하여 추가하는 방식으로 리스트 요소에 요소 하나를 추가하기 위한 메서드를 실행하면 수정 형식으로 메서드를 호출한 리스트는 변경되어 저장됩니다.
>>> a = [10, 20, 30]
>>> a.append(40)
>>> a
[10, 20, 30, 40]
>>> a = []
>>> a.append(10)
>>> a
[10]
# 리스트에 값 하나를 추가하여 저장할 수 있습니다.
# 빈 리스트에도 값을 추가할 수 있습니다.
이처럼 append는 하나의 값을 추가하여 저장할 때 사용합니다. 리스트 안에 리스트가 추가가 될 수 있는데 리스트 안에 리스트는 하나의 요소로 취급되어 append를 이용하여 리스트 안에 리스트를 넣을 수 있게 됩니다.
>>> a = [10, 20, 30]
>>> a.append([40, 50])
>>> a
[10, 20, 30, [40, 50]]
# 리스트 안에 리스트는 요소로 취급되어 바깥의 리스트에서는 하나로 판단됩니다.
# 리스트 안에 리스트로 길이를 구하는 len을 이용하여 a의 길이를 확인하면 4가 나오는 것을 확인 할 수 있습니다.
리스트 안에 값을 여러 개를 넣고자 할 때는 확장을 이용하면 됩니다. 확장은 리스트 끝에 다른 리스트를 연결하여 리스트를 확장하는 방식을 말하며, extend(리스트) 형식으로 호출합니다.
>>> a = [10, 20, 30]
>>> a.extend([40, 50])
>>> a
[10, 20, 30, 40, 50]
이와 같이 extend는 리스트 끝에 리스트를 연결하여 추가하는 방식입니다.
리스트의 특정 인덱스에 요소를 추가하는 방법도 있는데 insert(인덱스, 요소)의 방식으로 리스트의 특정 인데스에 요소 하나를 추가할 수 있습니다.
>>> a = [10, 20, 30]
>>> a.insert(2, 15)
>>> a
[10, 20, 15, 30]
>>> a.insert(0, 0)
>>> a
[0, 10, 20, 15, 30]
>>> a.insert(len(a), 40)
>>> a
[0, 10, 20, 15, 30, 40]
# 특정 인덱스에 리스트를 추가할 수 있습니다.
# 0번 인덱스에 값을 추가하면 첫 번째 요소로 추가됩니다.
# 인덱스 범위를 벗어난 값을 추가하면 마지막 요소에 값이 추가됩니다.
insert 또한 append처럼 리스트 형식으로 값을 추가하면 리스트 안에 리스트가 생기는 방식으로 값이 추가됩니다.
전에 정리하였던 방법인 슬라이스 방법으로도 값을 추가할 수 있는데 범위를 지정하여 요소를 추가하거나 덮어쓸 수 있습니다.
>>> a = [10, 20, 30]
>>> a[0:2] = [1, 2]
>>> a
[1, 2, 30]
>>> a[0:0] = [0]
>>> a
[0, 1, 2, 20, 30]
# 값 10과 20의 인덱스를 지정하여 1과 2의 값으로 덮었습니다.
# 시작과 끝의 범위를 같게하여 값을 추가할 수 있습니다.
요소를 추가하였다면 삭제도 가능할 텐데, 삭제하는 방법은 pop과 remove 메서드를 이용하면 됩니다. pop은 마지막 요소 또는 특정 인덱스의 요소를 삭제하고, remove는 측정값을 찾아 삭제해줍니다.
>>> a = [10, 20, 30]
>>> a.pop()
30
>>> a
[10, 20]
>>> a.pop(1)
20
>>> a
[10]
>>> a = [10, 20, 30]
>>> a.remove(30)
>>> a
[10, 20]
# pop에 인덱스를 지정하지 않으면 마지막 값을 반환한 후 삭제합니다.
# pop에 인덱스를 지정하면 해당 인덱스의 값이 반환된 후 삭제됩니다.
# remove는 값을 찾아 삭제하는데 값을 지정하지 않으면 에러가 발생됩니다.
# remove는 동일한 값이 여러개일 때 처음 찾은 값(인덱스 번호가 낮은 값)을 먼저 삭제합니다.
지금까지 정리한 메서드로 스택(stack)과 큐(queue) 구조를 리스트로 만들 수 있습니다. 스택(stack)은 append()로 요소를 추가하고 pop()을 통해 요소가 삭제되는 구조로 한쪽으로만 입출력이 되고 나중에 들어간 값이 먼저 삭제될 수 있는 구조입니다. 큐의 구조는 입력과 출력이 따로 돼있는 구조인데 먼저 들어간 값이 나오는 형태로 되어 있습니다. append()와 pop()의 사용에서 pop() 대신 pop(0)을 사용하거나 insert(0, 요소), pop()을 사용하면 추가와 삭제의 방향이 반대가 되어 큐 형식이 됩니다.
값을 삭제하기 전 리스트에서 값이 몇 개가 있는지 인덱스 번호가 무엇인지 찾을 경우도 있습니다. 그런 경우를 대비하여 리스트에서 특정 값의 개수와 인덱스를 찾을 수 있는 메서드를 제공을 합니다.
count와 index메서드로 index(값)과 count(값) 형식으로 호출됩니다.
>>> a = [10, 10, 20, 30, 40]
>>> a.index(10)
0
>>> a.count(10)
2
# a리스트에 10의 값이 2개가 있어 먼저 있던 10의 인덱스 번호를 반환하였습니다.
# a리스트에 10이 몇 개인지 반환해주었습니다.
이렇게 값이 여러 개일 때는 정렬이 필요할 것입니다. 정렬을 하는 데에는 작은 순서대로 정렬(오름차순)하는 방법과 큰 순서대로 정렬(내림차순)하는 방법이 있을 것입니다.
정렬을 하기 위해서는 sort() 메서드를 이용하면 순서대로 정렬이 가능합니다.
>>> a = [10, 10, 20, 30, 40, 20, 25, 30]
>>> a.sort()
>>> a
[10, 10, 20, 20, 25, 30, 30, 40]
# 작은 순서대로 정렬(오름차순)이 되었습니다.
sort를 이용하면 오름차순으로 정렬이 됩니다. 오름차순이 아닌 내림차순으로 정렬하기 위해서는 다음과 같은 방법들이 필요한데 순서를 뒤집는 메서드 reverse가 필요하게 됩니다.
>>> a.reverse()
>>> a
[40, 30, 30, 25, 20, 20, 10, 10]
>>> a.sort(reverse=True)
>>> a
[40, 30, 30, 25, 20, 20, 10, 10]
>>> a.sort(reverse=False)
>>> a
[10, 10, 20, 20, 25, 30, 30, 40]
# sort를 이용한 정렬이 되있는 상태에서 reverse를 이용한 리스트 순서를 뒤집는 방법입니다.
# sort메서드 안에 reverse메서드의 상태를 True로 하여 작은 순서의 역순 큰 순서대로 정렬(내림차순)합니다.
# sort메서드 안에 reverse메서드를 False로 주면 sort()와 같은 역할을 수행합니다.
리스트의 모든 요소를 삭제하고 싶을 때는 clear메서드를 사용하면 됩니다. clear대신 del함수를 이용할 수 있는데 시작 인덱스와 끝 인덱스를 생략하여 모든 요소를 삭제하라는 명령을 내리면 됩니다.
>>> a
[10, 10, 20, 20, 25, 30, 30, 40]
>>> a.clear()
>>> a
[]
# 모두 삭제되어 빈 리스트가 되었습니다.
리스트는 메서드를 이용하지 않고, 슬라이스 조작으로 append와 extend의 기능을 사용할 수 있습니다.
>>> a = [10, 20, 30]
>>> a[len(a):] = [40]
>>> a
[10, 20, 30, 40]
>>> a[len(a):] = [50, 60, 70]
>>> a
[10, 20, 30, 40, 50, 60, 70]
# 범위를 지정하여 값의 위치를 설정할 수 있으며,
# 리스트의 길이로 시작위치를 지정하여 리스트 마지막 인덱스에 값을 추가할 수 있습니다.
# 하나의 값을 추가하거나, 여러개의 값을 추가할 수 있습니다.
이제 할당과 복사에 대해 보겠습니다.
할당과 복사는 차이점이 있는데 같은 공간을 사용하는 것에 있습니다.
a = [0, 0, 0]의 리스트가 있을 때, b = a와 같이 a의 값을 b에게 할당 연산자(=)를 사용하여 할당하였을 때는 a가 가지고 있는 값의 주소를 b에게도 동일한 값의 주소를 할당하는 형식이 되게 됩니다. 그렇기에 a와 b는 같은 공간을 공유하고 있는 상태가 되며 둘 중 하나를 이용하여 값을 수정하면 두 변수를 호출하였을 때는 값이 모두 변경되었다는 것을 알 수 있습니다.
a와 b는 같은 객체이고 이름만 다르게 설정된 것입니다. 다른 객체로 생성하기 위해서는 복사의 과정이 필요합니다.
복사는 copy메서드를 이용하여 모든 요소를 복사하면 서로 다른 객체가 됩니다.
>>> a=[0, 0, 0]
>>> b = a.copy()
>>> a
[0, 0, 0]
>>> b
[0, 0, 0]
>>> a is b
False
# 서로 다른 객체인 것을 is연산을 통해 확인할 수 있습니다.
반복문으로 리스트의 요소를 모두 출력할 수도 있습니다. 인덱스를 지정하여 요소를 하나씩 꺼내어 출력하기에는 요소가 많을 때는 시간이 오래 걸릴 것입니다. 그렇기에 반복문을 이용하여 요소들을 출력할 수 있습니다.
for반복문과 while반복문을 이용하면 되는데, for 방법부터 보겠습니다.
for반복문에서는 요소의 값을 출력하는 것과 인덱스 번호와 같이 출력하는 방법이 다릅니다. 요소의 값은 for을 이용하여 간단하게 출력할 수 있지만 인덱스의 번호도 출력하기 위해서는 enumerate(리스트, start=숫자) 함수를 사용하여야 됩니다. 사용법은 아래와 같습니다.
>>>a = [10, 20, 30]
>>>for i in a:
print(i)
10
20
30
>>>for i in range(len(a)):
print(a[i])
10
20
30
>>>for index, value in enumerate(a):
print(index, value)
0 10
1 20
2 30
>>>for i, v in enumerate(a, start=1):
print(i, v)
1 10
2 20
3 30
# 일반적인 for형식으로 요소의 값을 출력할 수 있습니다.
# 인덱스로 요소를 반환받을 수 있습니다.
# enumerate함수를 이용하여 인덱스 번호를 0번부터 출력합니다.
# enumerate함수의 시작순서를 1부터 출력합니다. 이때, 번호만 1부터 출력됩니다.
enumerate함수는 열거하다는 뜻으로 순서가 있는 자료형을 입력을 받아 인덱스의 값을 포함하는 객체를 반환합니다.
while을 이용하여 요소를 출력하는 방법에는 부등호를 사용하면 됩니다.
>>>a = [10, 20, 30]
>>>i = 0
>>>while i < len(a):
print(a[i])
i += 1
10
20
30
# 부등호의 잘못된 사용은 에러 발생의 원인입니다.
리스트의 범위를 잘 생각하여 조건식을 만들어야 합니다.
리스트에서의 가장 작은 수와 가장 큰 수 그리고 합계를 구하는 방법을 반복문과 조건문을 응용하여 구할 수 있습니다.
작은 값을 저장시키는 변수에 인덱스 0의 요소가 들어있는 리스트를 만들고, 숫자를 계속 비교하여 숫자가 작으면 변수에 저장하는 방식을 먼저 보여드리겠습니다.
>>>a = [100, 30, 50, 70, 10]
>>>s = a[0]
>>>s
100
>>>for i in a:
if i < s:
s = i
>>> s
10
# s변수에 a리스트 첫 번째 요소를 할당하고
# 리스트의 다음 값과 비교하도록 만들어 가장 작은 값을 할당하는 방식입니다.
위의 방법을 활용하여 가장 큰 수도 쉽게 찾을 수 있습니다. 조건식에서 부등호의 방향만 변경하여 가장 큰 수를 변수에 넣게 할 수도 있습니다.
가장 큰 수와 작은 수를 구하는 다른 방법으로는 리스트를 정렬하여 구하는 방법입니다.
오름차순이면 가장 작은 수가 0번 인덱스에 있고, 가장 큰 수는 마지막 인덱스에 있을 것입니다. a.sort()를 이용하여 a[0]을 반환받으면 가장 작은 수가 될 것이고 a[-1]을 반환받으면 가장 큰 수가 될 것입니다. 이외의 정렬방법으로 구할 수 있는 방법들이 있을 것입니다.
파이썬에서 이것들보다 더 쉽게 작은 값과 큰 값을 구할 수 있는데 min과 max의 함수를 이용하는 방법입니다.
min함수는 리스트에서 가장 작은 값을 구하고, max는 가장 큰 값을 구합니다.
>>> a = [100, 30, 50, 70, 10]
>>> min(a)
10
>>> max(a)
100
요소의 합계를 구하는 방법 또한 반복문의 사용부터 알아보겠습니다.
>>>a = [100, 30, 50, 70, 10]
>>>x = 0
>>>for i in a:
x += i
>>> x
260
# 합계를 저장할 변수를 선언하여 값을 저장하도록 하였습니다.
합계를 저장할 변수를 선언할 때 초기값을 선언해야 합니다. 반복문을 사용하지 않고 더 간단하게 함수를 이용하여 합계를 구할 수 있는데 sum함수를 이용하면 됩니다. sum함수도 min과 max처럼 sum(리스트) 형식으로 호출하면 리스트의 요소의 합계를 반환합니다.
min과 max, sum은 반복 가능한 객체(iterable)를 넣어 사용할 수 있습니다.
반복문과 조건문을 식으로 표현하는 표현식에 대해 알아보겠습니다. 먼저, 리스트의 표현식으로 for반복문과 if조건문을 사용할 수 있는 형식입니다.
식, for반복문, if조건문 등을 지정하여 리스트를 생성하는 것을 리스트 컴프리헨션(list comprehension)이라 합니다.
컴프리헨션은 하나 이상의 이터레이터(iterator)로 자료구조를 만드는 것으로 리스트 컴프리헨션은 식을 지정하여 생성된 것을 리스트로 만들어 잡아두는 것입니다.
[식 for 변수 in 리스트]와 list(식 for 변수 in 리스트) 형식으로 사용됩니다.
식 부분에 값을 더하거나 다른 값과 연산하면 각 연산의 결과를 리스트로 만듭니다. 리스트 뒷부분에 if조건문을 지정할 수도 있습니다. 조건식에 만족하는 정보만 넘겨주게 됩니다. 정확한 사용방법은 다음과 같습니다.
>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = [i for i in range(10) if i % 2 == 0]
>>> a
[0, 2, 4, 6, 8]
for반복문과 if조건문을 여러 번 사용하여 코드를 작성할 수 있을 것입니다.
[식 for 변수1 in 리스트1 if 조건식1 for 변수2 in 리스트2 if 조건식2 ''' for 변수n in 리스트n if 조건식n]
list(식 for 변수1 in 리스트1 if 조건식1 for 변수2 in 리스트2 if 조건식2 ''' for 변수n in 리스트n if 조건식n)
>>> a = [i * j for j in range(2, 10) for i in range(1, 10)]
>>> a
[2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]
>>> a = [i * j for j in range(2, 10)
for i in range(1, 10)]
# for이 여러개일 때 처리 순서는 뒤에서 앞으로 처리됩니다.
# 들여쓰기는 하지않아도 되지만 가독성을 위해 해줍니다.
리스트에서 요소를 지정된 함수로 처리해주기 위해 map이 사용되는데 map은 원본 리스트를 변경하지 않고 새 리스트를 생성하므로 튜플에도 적용이 가능합니다.
list(map(함수, 리스트))
tuple(map(함수, 튜플))
>>> a = [10.5, 15.5, 20.5]
>>> for i in range(len(a)):
a[i] = int(a[i])
>>> a
[10, 15, 20]
>>> a = [10.5, 15.5, 20.5]
>>> a = list(map(int, a))
>>> a
[10, 15, 20]
# 반복문을 통해 모든 값을 정수로 변환하였지만 이보다 더 쉬운코드를 위해 map을 이용합니다.
값을 input().split()으로 여러 값을 입력받으면 값이 리스트로 돼있는 것을 확인할 수 있습니다. 여기에 map을 이용하면 map이 반환하는 맵 객체는 이터레이터(iterator)라서 변수 여러 개에 저장하는 언패킹(unpacking)이 가능하여 변수 여러 개에 저장할 수 있습니다.
튜플은 리스트와 다르게 내용을 변경할 수 없는 불변(immutable)의 법칙을 가지고 있습니다. 내용을 변경하는 메서드는 사용할 수 없으며, 요소의 정보를 구하는 메서드만 사용 가능합니다.
특정 값의 인덱스를 구하는 index메서드, 특정 값의 개수를 구하는 count메서드, 반복문을 이용한 요소 출력과 같은 값의 변화를 이용하지 않는 메서드만을 사용할 수 있습니다.
지금부터는 2차원 리스트의 사용입니다.
2차원 리스트는 [가로 x 세로] 형태로 이루어져 있으며 행(row)과 열(column) 모두 0부터 시작합니다.
2차원 리스트는 리스트 안에 리스트를 넣어 만들 수 있으며, 리스트 = [[값, 값], [값, 값], [값, 값]]과 같이 안쪽의 각 리스트는 콤마(,)로 구분하여 행의 길이를 만듭니다.
2차원 리스트의 요소에 접근하기 위해서는 리스트[세로 인덱스][가로 인덱스]를 호출하거나, 리스트[세로 인덱스][가로 인덱스] = 값으로 몇 행 몇 열 요소에 값을 할당할 수 있습니다.
예제로는 반복문을 이용하여 2차원 리스트의 요소를 모두 출력하는 것입니다. 코드는 다음과 같습니다.
>>> a = [[10, 20], [30, 40], [50, 60]]
>>> for i in a:
for j in i:
print(j, end=' ')
print()
10 20
30 40
50 60
>>>
>>> for i in range(len(a)):
for j in range(len(a[i])):
print(a[i][j], end=' ')
print()
10 20
30 40
50 60
>>>
>>> i = 0
>>> while i < len(a):
x, y = a[i]
print(x, y)
i += 1
10 20
30 40
50 60
>>>
>>> i = 0
>>> while i < len(a):
j = 0
while j < len(a[i]):
print(a[i][j], end=' ')
j +=1
print()
i += 1
10 20
30 40
50 60
# for반복문을 이용하여 2차원 배열형태를 출력하였습니다.
# while을 이용하여 2차원 배열형태를 출력하였습니다.
반복문으로 리스트를 만들 수 있습니다. 1차원 리스트, 2차원 리스트 모두 가능한데 1차원 리스트는 지금까지 사용했던 방법으로 append로 요소를 추가하며 리스트를 만드는 방법입니다. 2차원 리스트는 세로 크기만큼 반복하면서 안쪽 리스트로 사용할 수 있는 빈 리스트를 만들어 append로 요소를 추가하는 방식입니다. 예제로 보여드리겠습니다.
>>> a = []
>>> for i in range(5):
a.append(0)
>>> print(a)
[0, 0, 0, 0, 0]
>>> a = []
>>> for i in range(3):
line = []
for j in range(2):
line.append(0)
a.append(line)
>>> print(a)
[[0, 0], [0, 0], [0, 0]]
# 1차원 리스트를 만드는 방법입니다. append의 값을 변경하여 원하는 값을 추가할 수 있습니다.
# 2차원 리스트를 만드는 방법입니다. line변수를 이용하여 안에 값을 추가합니다.
위의 반복문을 표현식으로 간략하게 표현하여 2차원 리스트를 간단한 코드로 작성할 수 있습니다.
a = [[0 for j in range(2)] for i in range(3)]과 같이 해주거나 a = [[0] * 2 for i in range(3)]처럼 리스트 자체를 곱하여 표현할 수 있습니다.
크기가 불규칙한 리스트가 있을 수 있는데 위의 반복식에서 가로 크기를 지정해주는 리스트를 추가하여 반복문 조건에 넣어주면 됩니다.
이렇게 2차원 리스트를 만든 뒤 다른 변수에 할당하고, 요소를 변경하여 두 리스트의 값 변화를 확인할 수 있습니다.
2차원 리스트는 copy메서드를 이용하여도 변경이 아닌 할당이 되는 모습을 볼 수 있습니다. 2차원 이상의 다차원 리스트는 둘러 싸여있기에 복사를 하기 위해서는 copy메서드 대신 copy모듈의 deepcopy를 이용해야 합니다.
>>> a = [[0, 0], [0, 0], [0, 0]]
>>> import copy
>>> b = copy.deepcopy(a)
>>> b
[[0, 0], [0, 0], [0, 0]]
>>> a is b
False
# 두 객체를 비교하였을 때 False가 나왔기에 할당이 아닌 복사가 된 것을 알 수 있습니다.
2. 문자열의 응용
문자열은 문자열을 조작하거나 정보를 얻는 다양한 메서드(method)를 제공하는데 그중 자주 사용하는 것을 정리하겠습니다.
특정 문자열을 새로운 문자열로 변환하는 메서드를 replace('바꿀 문자열', '새 문자열') 사용합니다.
replace는 문자열 안의 문자열을 다른 문자열로 바꾸어 수정합니다. 예제를 보겠습니다.
변수.replace('바꿀 문자열', '새 문자열')
'문자열'.replace('바꿀 문자열', '새 문자열')
>>> s = 'Hello, world!'
>>> s = s.replace('world', 'Python')
>>> s
'Hello, Python!'
# world가 Python으로 변경되었습니다.
문자열을 바꿀 수 있다면 문자를 바꿀 수도 있을 것입니다.
translate는 문자열 안의 문자를 다른 문자로 바꾸는데 str.maketrans('바꿀 문자', '새 문자')로 변환 테이블을 만든 후 translate(테이블) 형식을 사용하면 문자를 바꿀 수 있습니다.
>>> a = str.maketrans('abc', '123')
>>> 'apple'.translate(a)
'1pple'
# 테이블을 사용하여 a, b, c를 1, 2, 3의 문자로 치환하는 테이블을 생성했습니다.
# apple이라는 문자에서 테이블에 속한 문자로 변환하여 반환하였습니다.
문자열을 분리할 수 있는데 split()의 메서드를 사용하여 문자열을 분리할 수 있습니다. 기본값은 공백으로 분류하며 괄호 안에 특정 문자를 넣어 분류기준을 바꿀 수 있습니다.
split()은 input()을 사용하며 많이 이용하였기에 생략하겠습니다.
문자열을 분리하여 리스트로 만든 후 구분자를 이용하여 문자열과 문자열 리스트를 연결할 수 있습니다. join(리스트)을 사용하여 구분자 문자열과 문자열 리스트의 요소를 연결하여 문자열로 만듭니다.
>>> '-'.join(['apple', 'banana', 'pineapple'])
'apple-banana-pineapple'
# '-'구분자를 이용하여 리스트안에 있는 문자열을 서로 연결하여 하나의 문자열로 만들었습니다.
문자를 변경할 수 있는데 소문자를 대문자로 대문자를 소문자로 변경이 가능합니다.
upper()과 lower() 메서드를 사용하여 간단하게 문자열을 바꿀 수 있습니다.
'Python'.upper()을 사용하면 모두 앞에 있던 문자열은 모두 대문자가 되고 lower()을 사용하면 모두 소문자가 됩니다.
문자열을 사용하다 보면 공백들을 삭제하거나 특정 문자를 삭제할 경우가 있습니다. 이때 lstrip, rstrip, strip메서드를 사용하여 공백을 제거하고 특정 문자들을 삭제할 수 있습니다.
>>> ' Python '.lstrip()
'Python '
>>> ' Python '.rstrip()
' Python'
>>> ' Python '.strip()
'Python'
# 모두 왼쪽, 오른쪽, 양쪽 공백을 제거하였습니다.
>>> ', Python ,'.lstrip(',')
' Python ,'
>>> ', Python ,'.rstrip(',')
', Python '
>>> ', Python ,'.strip(',')
' Python '
# 문자열 기준으로 왼쪽, 오른쪽, 양쪽의 지정문자가 제거되었습니다.
삭제할 문자를 strip메서드 괄호 안에 지정하면 문자열의 양쪽에 해당되는 문자를 삭제합니다. 양쪽의 구두점을 삭제하는 방법으로는 string모듈의 punctuation에 모든 구두점이 들어있기에 strip괄호 안에 string.punctuation을 지정하면 양쪽의 구두점은 쉽게 삭제될 것입니다.
공백을 삭제하는 방법을 알아보았다면 이제 문자열에 공백을 포함하는 정렬을 알아보겠습니다. ljust, rjust, center를 이용하여 정렬하면 됩니다.
왼쪽에 정렬하기 위해 ljust(길이)를 지정하면 되고 길이가 문자열보다 짧을 때는 그대로 출력됩니다. 문자열보다 길 때는 문자는 왼쪽에 있는 상태에서 공백이 오른쪽에 생기게 됩니다. 공백의 개수는 지정한 길이에서 문자열의 길이를 뺀 만큼의 길이가 생기게 됩니다. 다른 정렬들 또한 왼쪽, 오른쪽, 가운데만 다를 뿐 사용방법은 같습니다. 여기서 가운데는 공백의 길이 숫자가 홀수일 때 왼쪽에 하나가 더 들어가 정렬됩니다.
문자열을 정렬할 때, 공백에 숫자 0을 채울 수 있는데 zfill(길이)를 이용하여 지정된 길이에 맞춰 문자열의 왼쪽에 0을 채웁니다. zfill은 zero fill을 의미하며 문자열보다 길이가 작다면 아무것도 채우지 않고 반환합니다.
문자열의 위치를 찾을 수 있는데 find('찾을 문자열') 형식으로 호출하면 문자열에서 특정 문자열을 찾고, 문자열의 인덱스를 반환합니다. 문자열이 없을 때는 -1을 반환하여 문자열의 유무도 알려줍니다. 같은 문자열이 있을 때는 인덱스 번호가 낮은 것을 반환해줍니다.
오른쪽부터 문자열을 찾을 수 있는데 rfind('찾을 문자열')을 사용하면 됩니다. find의 반대로 같은 문자열이 있을 때, 인덱스 번호가 높은 것을 반환해줍니다.
find와 rfind 이외에도 문자열의 위치를 찾을 수 있는데 index와 rindex를 이용하면 됩니다. index('찾을 문자열')와 rindex('찾을 문자열')는 find, rfind와 같지만, 문자열이 없을 때 에러를 출력합니다.
찾고자 하는 문자열의 개수를 알고 싶을 때는 count('찾을 문자열')을 이용하여 사용하면 됩니다. 특정 문자열이 몇 번 반환되는지 알아내어 숫자로 반환해줍니다.
이러한 문자열 메서드는 처리한 결과를 반환하도록 만들어지므로 메서드를 줄줄이 연결하여 호출하는 메서드 체이닝(method chaining)이 가능합니다. 메서드 체이닝의 예로 input().split()이 대표적입니다. input()으로 반환받은 문자열에 split을 호출하는 방식입니다.
문자열을 다양한 방법으로 만들 수 있는데 서식 지정자(format specifier)와 문자열 포매팅(string formatting)을 이용하면 됩니다. 특정한 값이 원하는 값으로 바뀌는 것을 서식 지정자 또는 문자열 포매팅을 이용하여 사용하게 됩니다.
먼저, 서식 지정자부터 알아보겠습니다. 서식 지정자는 아래와 같은 방법을 사용하여 특정 값을 문자열, 숫자, 소수점 기준으로 값의 변화를 사용할 수 있습니다.
# 서식 지정자 문자열 넣기 : '%s' % '문자열' , '%정렬길이s' % '문자열'
# 서식 지정자 숫자 넣기 : '%d' % '숫자'
# 서식 지정자 소수점 넣기 : '%f' % '소수점' , '%.자릿수f' % '소수점'
# 문자열 넣기에서 정렬길이가 양수이면 오른쪽 정렬이고, 음수이면 왼쪽정렬입니다.
>>> 'I am %s' % 'Python'
'I am Python'
또한, 여러 지정자를 설정하여 값을 출력할 수 있는데 이때는 서식 지정자의 개수와 값(변수)의 개수를 동일하게 맞추어야 합니다. '%d %s' % (숫자, '문자열')과 같이 해야 합니다.
파이썬은 서식 지정자보다 더 간단한 문자열 포매팅을 제공하는데 문자열 포매팅은 중괄호({})를 사용하여 포매팅을 지정하고 format메서드로 값을 넣습니다.
# '{인덱스}'.format(값)
# '{인덱스}{인덱스}{인덱스}'.format(값)
>>> 'Hello, {0}'.format('world!')
'Hello, world!'
>>> 'Hello, {0} {2} {1}'.format('world!', 3.6, 'Script')
'Hello, world! Script 3.6'
>>> '{2} {0} {1} {2}'.format('world!', 3.6, 'Script')
'Script world! 3.6 Script'
>>> 'Hello, {} {} {}'.format('world!', 3.6, 'Script')
'Hello, world! 3.6 Script'
>>> 'Hello, {lang} {version}'.format(lang = 'Python', version = 3.6)
'Hello, Python 3.6'
# 여러개의 값을 인덱스의 순서대로 지정할 수 있습니다.
# 같은 값을 중복하여 지정할 수 있습니다.
# 인덱스 생략 시 순서대로 지정됩니다.
# 이름을 지정할 수 있습니다.
파이썬 3.6부터는 문자열을 더 간단하게 변수에 값을 넣고 문자열 앞에 포매팅이라는 뜻을 가진 f를 붙인 후, 중괄호({})에 변수 이름을 지정하면 간단하게 출력할 수 있습니다.
format메서드를 이용하여 문자열을 정렬할 수 있는데 인덱스 뒤에 콜론(:)을 붙이고 정렬할 방향과 길이를 지정하면 됩니다.
'{인덱스:<길이}'.format(값)의 형태로 부등호가 '<'이면 왼쪽부터 정렬하고 '>'일 때는 오른쪽부터 정렬하며 남은 공간은 공백으로 채워집니다. 여기서 인덱스를 사용하지 않고 처음부터 지정하면 인덱스는 생략이 가능합니다.
정수와 실수 앞에 0을 넣어 개수를 맞출 수 있는데 %d사이에 0과 자릿수를 넣어 '{인덱스:0개수d}'.format(숫자)를 해주면 됩니다. 실수(float)도 마찬가지로 %0개수.자릿수f' % 숫자 형식으로 가능합니다.
정렬을 통한 남은 공간에 0을 채울 수도 있습니다. '{인덱스:[[채우기]정렬][길이][.자릿수][자료형]}'형식으로 가능하며 '{0:0<10}'.format(15)을 해주면 길이 10으로 왼쪽 정렬하고 남는 공간은 0으로 채웁니다.
2. 딕셔너리의 활용
딕셔너리의 키-값 쌍을 조작하는 메서드와 정보를 조회하는 메서드에 대해 정리하겠습니다.
setdefault: 키-값 쌍 추가
update: 키의 값 수정, 키가 없으면 키-값 쌍 추가
키-값 쌍을 추가하는 메서드입니다. setdefault은 딕셔너리에 키-값 쌍을 추가하고 setdefault에 키만 지정되었을 때는 값에 None을 저장합니다. 기본적으로는 값을 넣어 추가하여 반환하는 setdefault(키, 기본값) 형태입니다.
>>> x = {'a': 10, 'b': 20, 'c':30}
>>> x.setdefault('d')
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': None}
>>> x.setdefault('e', 50)
50
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': None, 'e': 50}
키-값 상을 추가하는 것이 아닌 변경할 수 있는데 update메서드를 사용하면 됩니다. update는 딕셔너리를 넣어 값을 수정할 수 있고, 키와 값을 넣어 사용이 가능합니다.
>>> x = {'a': 10, 'b': 20, 'c':30}
>>> x.update(a = 1)
>>> x
{'a': 1, 'b': 20, 'c': 30}
>>> x.update(a = 10, d = 40)
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.update({1: 1, 2: 2})
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 1: 1, 2: 2}
>>> x.update([[1, '하나'],[2, '둘']])
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 1: '하나', 2: '둘'}
>>>
>>> x.update(((1, 1),(2, 2)))
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 1: 1, 2: 2}
>>> x.update(zip([1, 2], ['one', 'two']))
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 1: 'one', 2: 'two'}
# 키-값 쌍을 설정하여 수정하였습니다.
# 업데이트하려는 키-값 쌍이 딕셔너리에 없으면 키-값 쌍을 추가합니다.
# 여러 개를 콤마(,)로 구분하여 넣을 수 있습니다.
# update(키=값)은 키가 문자열일 때 사용하고 update(딕셔너리)는 키가 숫자일 때 사용합니다.
# 리스트와 튜플을 이용하여 업데이트할 수 있습니다.
# update(반복가능한 객체)로 키-값 쌍을 수정할 수 있습니다.
추가하는 것과 반대로 삭제하는 메서드를 이용해보겠습니다. 특정 키-값 쌍을 삭제하는 메서드로는 pop을 이용한 삭제와 del을 이용한 삭제 방법이 있습니다.
pop에는 삭제명령을 내렸을 때 삭제할 값이 없으면 기본값을 출력하도록 설정이 가능합니다.
>>> x = {'a': 10, 'b': 20, 'c':30}
>>> x.pop('a')
10
>>> x
{'b': 20, 'c': 30}
>>> x.pop('d', 0)
0
>>> del x['b']
>>> x
{'c': 30}
# pop(키)를 이용하여 키의 값을 삭제하였습니다.
# pop(키, 기본값)을 이용하여 삭제하려는 키가 없을 때 기본값을 반환하게 하는 코드입니다.
# del을 이용하여 해당 키를 삭제할 수 있습니다.
특정 키를 삭제하는 것이 아닌 임의의 키-값을 삭제한 뒤 삭제한 키-값 쌍을 튜플로 반환하는 메서드가 있습니다. popitem() 메서드이며 파이썬 3.6 이상부터는 마지막 키-값 쌍을 삭제합니다. 딕셔너리의 모든 값을 삭제하기 위해서는 clear() 메서드를 사용하면 빈 딕셔너리가 되는 것을 볼 수 있습니다.
>>> x = {'a': 10, 'b': 20, 'c':30}
>>> x.popitem()
('c', 30)
>>> x
{'a': 10, 'b': 20}
>>> x.clear()
>>> x
{}
# 파이썬 3.6부터는 마지막 딕셔너리 값을 삭제합니다.
# clear을 통해 빈 딕셔너리를 만들 수 있습니다.
딕셔너리에서 키의 값을 가져오거나 저장할 수 있습니다. get메서드를 사용하거나 items, keys, values로 키-값 쌍을 모두 가져올 수 있습니다.
get은 특정 키의 값을 가져옵니다. 기본값을 지정하면 키가 없을 때 기본값을 반환하여 키가 없다는 것을 알려줍니다.
items는 딕셔너리의 키-값 쌍을 모두 가져오며, keys는 모든 키를 가져옵니다. 마지막으로 values는 모든 값을 가져오는 메서드입니다. 예제로 살펴보겠습니다.
>>> x = {'a': 10, 'b': 20, 'c':30}
>>> x.get('a')
10
>>> x.get('d',0)
0
>>> x.items()
dict_items([('a', 10), ('b', 20), ('c', 30)])
>>> x.keys()
dict_keys(['a', 'b', 'c'])
>>> x.values()
dict_values([10, 20, 30])
# get을 통한 특정 키의 값을 가져왔습니다.
# 모든 값의 정보를 items, keys, values를 통해 가져왔습니다.
이번에는 키가 정의되어 있는 리스트와 튜플 상태에서 값을 넣어 딕셔너리로 생성하는 메서드를 알아보겠습니다.
dict.fromkeys(키 리스트)는 키 리스트로 값이 None인 딕셔너리를 생성합니다. None의 값 대신 다른 값을 넣고자 한다면 키 리스트 옆에 값을 지정해주면 됩니다.
>>> key = ['a', 'b', 'c']
>>> x = dict.fromkeys(key)
>>> x
{'a': None, 'b': None, 'c': None}
>>> x = dict.fromkeys(key, 0)
>>> x
{'a': 0, 'b': 0, 'c': 0}
반복문을 이용하여 딕셔너리의 값을 모두 출력하기 위해서는 for 키, 값 in 딕셔너리.items()를 반복 선언 후 키와 값의 변수를 출력해주는 print함수를 호출해주면 됩니다.
이러한 for문을 이용할 때 리스트와 마찬가지로 딕셔너리도 for반복문과 if조건문을 사용하여 표현식을 생성할 수 있습니다.
{키: 값 for 키, 값 in 딕셔너리}
dict({키: 값 for 키, 값 in 딕셔너리})
위의 방식의 형태이며 dict.fromkeys 함수만 사용한 결과와 비슷하기에 딕셔너리 뒤에 if조건문을 달아 특정 값을 찾아 값을 제외하는데 유용합니다.(특정 키를 삭제하는 메서드만을 제공하기에 값을 삭제하기 위해서는 표현식을 이용해야 합니다.)
>>> key = ['a', 'b', 'c']
>>> x = {k: value for k, value in dict.fromkeys(key).items()}
>>> x
{'a': None, 'b': None, 'c': None}
>>> x = {k: value for k, value in {'a':10, 'b':20, 'c':30}.items()}
>>> x = {key: value for key, value in x.items() if value != 20}
>>> x
{'a': 10, 'c': 30}
# key 리스트에 있는 값을 모두 꺼내어 키-값 쌍을 구합니다.
# 키와 값을 하나씩 꺼내어 딕셔너리를 만듭니다.
# x에서 키-값 쌍을 구하여 20을 제외시킨 키와 값을 하나씩 꺼내어 딕셔너리를 생성합니다.
딕셔너리 안에서 딕셔너리를 사용하는 중첩 딕셔너리에 대해 보겠습니다.
딕셔너리 = {키1: {키A: 값A}, 키2: {키B: 값B}}의 형식이며 예제로 행성의 반지름, 질량, 공전 주기를 딕셔너리를 보겠습니다.
>>> terrestrial_planet = {
'Mercury': {
'mean_radius': 2439.7,
'mass': 3.3022E+23,
'orbital_period': 87.969
},
'Venus': {
'mean_radius': 6051.8,
'mass': 4.8676E+24,
'orbital_period': 224.70069,
},
'Earth': {
'mean_radius': 6371.0,
'mass': 5.97219E+24,
'orbital_period': 365.25641,
},
'Mars': {
'mean_radius': 3389.5,
'mass': 6.4185E+23,
'orbital_period': 686.9600,
}
}
>>> print(terrestrial_planet['Venus']['mean_radius'])
6051.8
# terrestrial_planet에 키 'Mercury', 'Venus', 'Earth', 'Mars'가 있고 이 키들은 다시 딕셔너리를 가지고 있습니다.
# 딕셔너리 안에 있는 딕셔너리에 접근하기 위해서는 단계만큼 대괄호([])를 붙이면 됩니다.
# 딕셔너리[키][키]
# 값을 수정하기 위해서는 딕셔너리[키][키] = 값을 해주면 됩니다.
이런 중첩 딕셔너리는 계층형 데이터를 저장할 때 유용합니다.
중첩 딕셔너리를 할당하는 법과 복사하는 방법에 대해 알아보겠습니다. 딕셔너리를 만든 뒤 다른 변수에 할당 연산자(=)를 이용하여 저장하게 되면 같은 공간을 사용하는 변수 2개가 만들어집니다. 변수 이름만 다르고 똑같은 장소에서 데이터를 가져와 둘 중 하나를 변경하면 두 곳도 변하는 것처럼 보일 것입니다. 복사하기 위해서는 copy메서드를 사용하면 복사가 되는데 중첩 딕셔너리에서는 copy메서드를 이용해도 할당과 같은 결과가 나옵니다.
중첩 딕셔너리를 완전히 복사하고 싶을 때는 copy대신 deepcopy메서드를 사용해야 합니다. deepcopy는 copy모듈을 가져온 후 메서드를 호출해야 합니다.
3. 세트와 집합
파이썬에서는 집합을 표현하는 세트(set)라는 자료형을 제공합니다. 세트는 합집합, 교집합, 차집합 등을 이용한 연산이 가능합니다.
세트를 만들기 위해서는 중괄호({}) 안에 값을 저장하며 각 값은 콤마(,)로 구분합니다.
세트 = {값1, 값2, 값3}의 형식이며 세트의 요소의 순서는 정해져 있지 않습니다. 세트에 들어가는 요소는 중복될 수 없어 두 개의 중복 요소가 들어가 있으면 하나만 출력됩니다.
세트는 리스트, 튜플, 딕셔너리와 다르게 대괄호([])로 특정 요소만을 출력할 수 없고 모두 출력됩니다.
그렇기에 세트에 특정값이 있는지 확인하기 위해서는 '값 in 세트'의 형식으로 세트(set) 안에 값이 있는지 불(bool) 형식으로 확인해야 합니다. 반대로 없는지 확인하는 방법은 '값 not in 세트'입니다.
set은 반복 가능한 객체(iterable)를 이용하여 만들 수 있습니다. set(반복 가능한 객체)이며, set('apple')과 같이 만들면 a의 set은 {'a', 'p', 'l', 'e'}가 순서 상관없이 중복된 값은 포함되지 않고 만들어질 것입니다.
만들어진 세트에서 집합 연산에 사용되는 메서드를 보겠습니다. 집합 연산은 산술 연산자와 논리 연산자를 활용합니다.
>>> a = {1, 2, 3}
>>> b = {3, 4, 5}
>>> a | b
{1, 2, 3, 4, 5}
>>> set.union(a, b)
{1, 2, 3, 4, 5}
>>> a & b
{3}
>>> set.intersection(a, b)
{3}
>>> a - b
{1, 2}
>>> set.difference(a, b)
{1, 2}
>>> a ^ b
{1, 2, 4, 5}
>>> set.symmetric_difference(a, b)
{1, 2, 4, 5}
# 두 세트를 생성합니다.
# a와 b의 합집합(union)을 구하며 or연산자(|)를 사용하거나 set.union메서드를 이용합니다.
# 교집합(intersection)을 구하며 and연산자(&)를 사용하거나 set.intersection메서드를 이용합니다.
# 차집합(difference)을 구하며 뺄셈연산자(-)를 사용하거나 set.difference를 이용합니다.
# 대칭차집합(symmetric difference)을 구하며 xor(^)을 사용하거나 set.symmetric_difference를 이용합니다.
세트 자료형에 집합 연산 후 할당 연산자를 이용하여 집합 연산의 결과를 변수에 다시 저장해보겠습니다.
>>> a = {1, 2, 3}
>>> a |= {4}
>>> a
{1, 2, 3, 4}
>>> a.update({5})
>>> a
{1, 2, 3, 4, 5}
>>> a &= {0, 1, 2, 3}
>>> a
{1, 2, 3}
>>> a.intersection_update({0, 1, 2, 3, 4})
>>> a
{1, 2, 3}
>>> a -= {3}
>>> a
{1, 2}
>>> a.difference_update({2})
>>> a
{1}
>>> a ^= {1, 2, 3}
>>> a
{2, 3}
>>> a.symmetric_difference_update({0, 1, 2, 3})
>>> a
{0, 1}
# 합집합
# 교집합
# 차집합
# 대칭차집합
세트는 부분집합, 진부분 집합, 상위 집합, 진 상위 집합과 같이 속하는 관계를 표현할 수 있는데 부등호와 메서드를 이용합니다. 다음과 같습니다.
>>> a = {0, 1}
>>> a <= {0, 1, 2}
True
>>> a.issubset({0, 1})
True
>>> a < {0, 1, 2}
True
>>> a >= {0, 1}
True
>>> a.issuperset({0})
True
>>> a > {0}
True
>>> a == {0, 1}
True
>>> a != {1, 2}
True
>>> a.isdisjoint({1, 2})
False
>>> a.isdisjoint({2, 3})
True
# '<='와 issubset을 통해 부분집합인가를 확인가능
# '<'를 통해 진부분집합인지를 확인가능
# '>='와 issuperset을 통해 상위집합을 확인가능
# '>'를 통해 진상위집합을 확인할 수 있습니다.
# ==와 !=를 통해 세트가 같은지 다른지 확인 할 수 있습니다.
# 세트가 겹치지 않는지 disjoint를 통해 확인 할 수 있습니다.
세트를 조작하는 방법과 개수를 구하는 것에 대해 알아보겠습니다.
세트에 요소를 추가, 삭제할 수 있습니다. add(요소)를 통해 세트에 요소를 추가할 수 있으며 remove(요소)를 통해 특정 요소를 삭제할 수 있습니다. remove는 요소가 없을 때 에러가 발생되므로 discard(요소)를 사용하여 요소가 없어도 에러를 발생하지 않도록 하는 메서드를 사용하기도 합니다.
특정 값이 아닌 임의의 요소를 삭제하고 반환받을 수 있습니다. pop() 메서드를 통해 임의의 요소를 삭제하고 요소를 반환합니다. 삭제할 요소가 없는 상태에서 사용할 경우 에러를 발생시킵니다. 모든 요소를 삭제하기 위해서 clear() 메서드를 사용합니다.
세트의 개수를 구할 때는 다른 것들과 마찬가지로 len함수를 이용하여 개수를 구할 수 있습니다. len(세트)를 호출하면 세트의 요소 개수(길이)가 구해집니다.
세트도 리스트, 딕셔너리처럼 할당과 복사가 가능합니다. 세트를 만들고 다른 변수에 할당(=)하면 다른 것들과 마찬가지로 공간이 같은 곳을 공유하고 있는 상태입니다.
복사가 아닌 할당이기에 값을 변환하면 다른 변수에서도 변환된 것처럼 보입니다. 복사를 하기 위해서는 copy메서드를 이용하여 모든 요소를 복사하면 됩니다.
세트에서의 표현식 사용은 for 변수 in 뒤에 세트만 지정하면 됩니다. 여기서 세트의 요소는 순서가 없다는 점을 기억하고 있어야 됩니다. 단, 숫자로만 이루어진 세트는 순서대로 출력됩니다.
세트 표현식에서 if조건문을 사용하려면 for 반복문 뒤에 있는 세트 뒤에 지정해야 합니다.
{식 for 변수 in 세트 if 조건식}
set(식 for 변수 in 세트 if 조건식)
위의 방법이며 if조건문에서 특정 조건을 충족하는 것을 꺼내어 세트로 만들게 됩니다.
4. 파일과 회문
먼저, 프로그래밍에서 중요한 부분인 파일 처리입니다. 파일에서 문자열을 읽고 쓰는 방법과 객체를 파일에 읽고 쓰는 것에 대해 정리하겠습니다.
파일에 문자열을 쓸 때는 open함수로 파일을 열어 파일 객체(file object)를 얻은 후 write메서드를 사용합니다.
파일 객체 = open(파일 이름, 파일 모드)
파일 객체.write('문자열')
파일 객체.close()
위의 순서대로 적용됩니다.
>>> file = open('hello.txt','w')
>>> file.write('hello, world!')
13
>>> file.close()
# hello.txt파일을 쓰기모드로 열어 파일객체로 반환합니다.
# file에 문자열을 저장하였습니다.
# file객체를 닫았습니다.
# 저장위치는 소스코드가 저장된 위치이거나 셸에서 입력하였다면 PATH를 적용했던 경로에 저장
# C:\사용자\사용자\AppData\Local\Programs\Python\Python39
파일을 읽을 때도 open을 이용하여 파일의 객체를 열어 읽어야 합니다. 여기서 파일을 다 읽고 나면 파일의 객체를 닫아야 하는데 잊어버리고 못 닫을 수 있습니다. 그런 경우를 위해 with as를 사용하여 파일을 사용한 뒤 자동으로 파일의 객체를 닫아주는 with open(파일 이름, 파일 모드) as 파일 객체를 이용합니다.
>>> file = open('hello.txt', 'r')
>>> s = file.read()
>>> print(s)
hello, world!
>>> file.close()
>>> with open('hello.txt', 'r') as file:
s = file.read()
print(s)
hello, world!
# hello.txt를 읽기모드('r')로 열어 파일을 읽은 후 파일 닫기 수행
# 자동 객체 닫기를 이용하여 파일을 읽은 후 자동으로 나가짐
파일의 내용을 여러 줄로 저장하거나 내용을 가져오는 방법도 여러 가지가 있습니다.
>>> with open('hello.txt', 'w') as file:
for i in range(3):
file.write('hello, world! {0}\n'.format(i))
16
16
16
>>> with open('hello.txt', 'r') as file:
print(file.read())
hello, world! 0
hello, world! 1
hello, world! 2
>>> line = ['안녕하세요.\n', '파이썬입니다.']
>>> with open('hello.txt', 'w') as file:
file.writelines(line)
>>> with open('hello.txt', 'r') as file:
print(file.read())
안녕하세요.
파이썬입니다.
>>> with open('hello.txt', 'r') as file:
lines = file.readlines()
print(lines)
['안녕하세요.\n', '파이썬입니다.']
>>> with open('hello.txt', 'r') as file:
line = None
while line != '':
line = file.readline()
print(line.strip('\n'))
안녕하세요.
파이썬입니다.
>>> with open('hello.txt', 'r') as file:
for line in file:
print(line.strip('\n'))
안녕하세요.
파이썬입니다.
# 반복문을 이용한 번호와 여러 문자열 작성
# 리스트에 들어있는 문자열 파일에 적용 파일객체.writelines(문자열리스트)
# 파일의 내용을 한 줄씩 리스트로 가져오는 변수 = 파일객체.readlines() 사용
# 파일의 내용을 한 줄 씩 순차적으로 읽어와 문자열에서 \n을 삭제하여 출력 변수 = 파일객체.readline()
# readline은 더 이상 읽을 줄이 없을 때 빈 문자열을 반환합니다.
# for반복문으로 파일의 내용을 한 줄씩 읽어 변수에 저장하여 출력
# 파일의 객체는 이터레이터, 여러개의 변수에 저장하여 언패킹이 가능합니다.
파일에서 문자열만 읽고 쓰는 것이 아닌 객체를 파일에 저장할 수 있습니다. pickle모듈을 제공하기 때문에 가능한데 파이썬 객체를 파일에 저장하는 과정을 피클링(pickling)이라 하며, 파일에서 객체를 읽어오는 과정을 언피클링(unpickling)이라 합니다.
피클링은 pickle모듈의 dump메서드를 사용하여 파일에 저장할 수 있습니다. 파일은 임의의 확장자를 사용하여 저장되고 pickle.dump로 객체(값)를 저장할 때는 파일 모드를 'wb'와 같이 바이너리(binary)의 약자인 b를 붙여 컴퓨터가 처리하는 파일 형식으로 만들어야 합니다.
객체를 읽기 위해서는 언피클링을 해야 하는데 pickle모듈에서 load를 사용하여야 합니다. 언피클링을 할 때는 반드시 파일 모드를 바이너리 읽기 모드'rb'로 설정하여 지정해야 합니다. 컴퓨터가 처리하는 컴퓨터만 읽을 수 있기에 읽기 위해서는 언피클링을 해줘야 합니다. 파일을 가져오는 것은 저장했던 순서로 가져오면 됩니다.
>>> import pickle
>>> name = 'larry'
>>> age = 22
>>> address = '서울시'
>>> with open('larry.p', 'wb') as file:
pickle.dump(name, file)
pickle.dump(age, file)
pickle.dump(address, file)
>>> import pickle
>>> with open('larry.p', 'rb') as file:
name = pickle.load(file)
age = pickle.load(file)
address = pickle.load(file)
print(name)
print(age)
print(address)
larry
22
서울시
# 저장할 때 파일모드를 wb로 하였습니다.
# 가져올 때는 rb로 설정하여 지정하였습니다.
아래는 파일 모드의 조합입니다. 읽기 모드 쓰기 모드와 같이 모드들에 대한 옵션이 있습니다.
이번에는 문자열을 응용하여 회문을 판별하고 N-gram을 만들겠습니다. 회문은 염기서열 분석에 많이 사용되고, N-gram은 빅 데이터 분석, 검색 엔진에서 많이 사용됩니다.
회문(palindrome)은 거꾸로 읽어도 뜻이 일치하는 것으로 양쪽의 값이 같습니다. 예로 'level', 'sos', 'rotator'등이 있습니다. 가운데 문자를 기준으로 왼쪽과 오른쪽을 비교하여 일치하면 회문입니다. 회문의 판별을 파이썬으로 나타내면 다음과 같습니다.
>>> word = input('단어를 입력 : ')
단어를 입력 : level
>>> true_palindrome = True
>>> for i in range(len(word) // 2):
if word[i] != word[-1 - i]:
true_palindrome = False
break
>>> print(true_palindrome)
True
>>> word = input('단어를 입력 : ')
단어를 입력 : hello
>>> print(word == word[::-1])
False
>>> word = input('단어를 입력 : ')
단어를 입력 : level
>>> list(word) == list(reversed(word))
True
>>> word = input('단어를 입력 : ')
단어를 입력 : level
>>> ''.join(reversed(word))
'level'
>>> ''.join(reversed(word)) == word
True
# 회문 판별 초기값을 True로 주어 마지막문자([-1])에서 i만큼 뺀 것과 비교하며 회문판단
# 문자열 전체에서 인덱스를 1감소 시키며 가져오는 것과 비교하여 회문판단
# 문자열을 역순하여 같으면 회문으로 판단
# 리스트의 요소를 연결한 역순과 같으면 회순으로 판단
N-gram은 문자열에서 N개의 연속된 요소를 추출하는 방법입니다. 2-gram이라 하면 문자(글자) 단위를 2개씩 중 처음에 온 하나의 문자를 제외한 문자가 계속 중복되며 출력되는 것입니다. 'Hello'이면 'He', 'el', 'll', 'lo'방식입니다.
파이썬에서 반복문과 zip함수로 N-gram을 만들 수 있습니다.
>>> text = 'Hello'
>>> for i in range(len(text) - 1):
print(text[i], text[i + 1], sep='')
He
el
ll
lo
>>> text = 'this is python'
>>> words = text.split()
>>> for i in range(len(words) - 1):
print(words[i], words[i + 1])
this is
is python
>>> text = 'hello'
>>> two_gram = zip(text, text[1:])
>>> for i in two_gram:
print(i[0], i[1], sep='')
he
el
ll
lo
# 인덱스 번호를 마지막 인덱스 번호보다 하나 적게하여 반복하여 출력합니다.
# 처음과 마지막을 제외한 문자는 계속 반복되며 출력됩니다.
# 문자열도 split메서드를 이용하여 리스트로 나눠 만들 수 있습니다.
# zip함수를 이용하여 인덱스 1부터 마지막 문장까지 가져오기에 text와 text[1:]을 zip으로 묶으면 문자 하나가 밀린 상태로 각 문자를 묶게 됩니다.
zip을 이용하여 N-gram을 만들 때 일일이 [1:], [2:]와 같은 슬라이스로 넣기가 불편하여 표현식으로 사용하게 되었습니다.
>>> text = 'hello'
>>> [text[i:] for i in range(3)]
['hello', 'ello', 'llo']
>>> zip([text[i:] for i in range(3)])
<zip object at 0x000001F50F046D40>
>>> list(zip([text[i:] for i in range(3)]))
[('hello',), ('ello',), ('llo',)]
>>> list(zip(*[text[i:] for i in range(3)]))
[('h', 'e', 'l'), ('e', 'l', 'l'), ('l', 'l', 'o')]
# range함수에는 N-gram의 N의 수를 넣으면 됩니다.
# zip에 넣어 반복가능한 객체의 각 요소를 튜플로 묶어줍니다.
# list로 만들어 출력해봅니다.
# zip에 리스트의 각 요소를 콤마(,)로 구분하여 넣어주려면 리스트 표현식 앞에 *을 붙여줘야 합니다.
5. 정리
리스트에 요소를 추가하는 방법으로 append(값), insert(인덱스, 요소), 리스트[인덱스 시작:]=값 형식입니다.
모든 요소를 삭제하는 방법은 clear이 있습니다.
모든 요소를 출력하는 방법으로 인덱스의 번호를 반복하여 출력하는 방법과 하나씩 꺼내어 출력하는 방법이 있습니다.
튜플은 출력과 새로 생성만 되고 변경과 같은 작업은 안됩니다.
리스트 표현식은 [식 for 변수 in 리스트 if 조건식]입니다.
리스트에서 map을 사용하기 위해 list(map(함수, 리스트))형식을 사용합니다.
리스트 a에 들어있는 문자열 중 길이가 5인 것들만 출력되는 코드
a = ['alpha', 'bravo', 'charlie']
b = [i for i in a if len(i) == 5]
2차원 배열을 만드는 방법으로 변수 = [[리스트], [리스트]]와 같은 형식으로 만듭니다.
2차원 배열의 출력 방법은 리스트[세로 리스트][가로 리스트]입니다.
표현식으로도 2차원 배열 생성이 가능합니다.
3차원 배열 높이 2, 세로 4, 가로 3인 리스트를 생성하는 코드
a = [[[0 for i in range(3)]for j in range(4)]for k in range(2)]
3차원 배열은 높이, 가로, 세로 형태이기에 리스트 = [[[값, 값], [값, 값]],[[값, 값],[값, 값]],[[값, 값], [값, 값]]]형식입니다.
리스트[높이 인덱스][세로 인덱스][가로 인덱스]
메서드의 활용으로 정렬, 찾기, 변환, 분리 등이 가능합니다.
파일 경로에서 파일명만 출력되는 코드
path = 'C:\user\user\AppData\Local\Programs\Python\Python39\Python.exe'
x = path.split('\')
filename = x[-1]
print(filename)
딕셔너리의 키와 값을 삭제하는 함수로 pop과 del이 존재합니다.
딕셔너리의 메서드 중 setdefault는 딕셔너리에 키-값 쌍을 추가합니다.
딕셔너리에서 특정 값을 찾아 삭제할 때 표현식에 if를 사용합니다.
중첩 딕셔너리의 값 출력은 딕셔너리[값][값] 형태로 찾아 내려가야 합니다.
중첩 딕셔너리의 복사는 deepcopy를 이용해야 합니다.
평균 점수가 출력되는 코드
larry = {'kor': 90, 'eng': 80, 'math': 85}
avg = sum(larry.values()) / len(larry)
print(avg)
세트를 만드는 법은 {}을 이용하거나 set()을 이용합니다.
합집합, 교집합, 차집합 등을 이용할 수 있습니다.
진부분 집합과 진상위 집합에는 메서드가 존재하지 않습니다.
1부터 100까지 숫자 중 3과 5의 공배수를 세트 형태로 출력하는 코드
a = {i for i in range(1,101) if i % 3 == 0}
b = {i for i in range(1,101) if i % 5 == 0}
print(a & b)
파일에 문자열을 쓰기 위해 파일 열기는 file=open(파일 이름, 모드'w')를 이용하여야 합니다.
파일에 문자열을 한 줄씩 읽어 리스트 형태로 가져오는 메서드는 readlines입니다.
pickle모듈로 파일에 저장된 파이썬의 객체를 읽어올 때 파일 열기 방법으로 file=open(파일 이름, 'rb')를 사용합니다.
words.txt 파일의 내용 중 10자 이하인 단어의 개수가 출력되는 코드
with open('words.txt', 'r') as file:
count = 0
words = file.readlines()
for word in words:
if len(word.strip('\n')) <= 10:
count += 1
입력된 숫자에 해당하는 N-gram을 튜플로 출력하는 코드
n = int(input())
text = input()
words = text.split()
if len(words) < n:
print('wrong')
else:
n-gram = zip(*[words[i:] for i in range(n)])
'TeamH4C_ProjectH4C > 프로그래밍 언어' 카테고리의 다른 글
[TeamH4C_CodeUp] 기초 100제_출력하기 (0) | 2021.02.02 |
---|---|
[TeamH4C_Python] 함수의 사용 (0) | 2021.01.31 |
[TeamH4C_Python] 선택과 반복 (0) | 2021.01.27 |
[TeamH4C_Python] 자료형의 비교와 문자열 (0) | 2021.01.21 |
[TeamH4C_Python] 변수와 데이터 (0) | 2021.01.20 |