(나도코딩의 파이썬 입문) 5장. 자료구조(p.123 ~ p.151)

2023. 2. 23. 01:15독서

반응형

안녕하세요!

<코딩 자율학습 나도코딩의 파이썬 입문> 멘토를 담당하게 된 이안입니다.

 

오늘은 5장 '자료구조'를 학습할 거예요!

vscode에서 ch05.py 파일을 생성하고 시작해 주세요.

 

 

오늘 공부할 내용은 다음과 같습니다.

 

🧐 공부할 내용(p.123~p.151)

  • 리스트
  • 딕셔너리
  • 튜플
  • 세트
  • 자료구조 변환하기

 

1. 리스트


리스트는 값을 여러 개 가질 수 있는 자료구조입니다.

리스트의 특징은 크기를 마음대로 늘렸다 줄였다 할 수 있고, 원소의 추가, 삭제가 용이해요.

 

또한 인덱스로 접근이 되고, 인덱스의 원소를 수정하는 것도 쉽게 가능하답니다.

 

 

파이썬의 문자열 기억나시죠?

파이썬의 문자열도 인덱스 접근이 됐었죠?

 

문자열은 변경이 불가능하지만, 리스트는 변경이 가능하답니다.

 

책에서는  추가/삽입/삭제, 중복 값 확인, 정렬, 확장 등 총 6개의 기능을 소개하고 있어요.

그럼 함께 알아보시죠!

 

 

1) 값 추가/삽입/삭제

저는 예제로 지하철역을 사용할 거예요.

2장에서 풀었던 실전문제 기억하시죠?

 

그것을 기반으로 예제를 해보겠습니다.

 

먼저 빈 리스트를 하나 생성해 주세요.

 

빈 리스트 생성은 책 p.126에 있습니다.

 

 

stations = []

 

 

역을 담을 리스트를 생성했어요.

 

그럼 이제 값을 추가해 보죠.

'사당'역을 추가해 볼까요?

 

 

stations = []

stations.append("사당")

print(stations)

 

print 문을 이용해 출력하시면 "사당"역이 추가된 stations을 확인하실 수 있어요.

 

 

그럼 나머지 2개 역도 함께 추가해 봐요.

stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

 

어때요 실행결과에서 3개의 역이 모두 나왔나요?

 

🥕멘토 TIP

파이썬은 C/C++과 다르게 배열이 존재하지 않고, 오직 리스트 형태만 존재합니다.

 

또한 리스트 자체가 객체이기 때문에 객체의 원소를 print문으로 출력해서 확인할 수 있죠.

 

 

 

p.127에서는 index 함수를 통해서 원소의 인덱스를 출력하는 예제를 설명하고 있어요.

한번 "신도림"의 index를 직접 출력해 보세요!

 

 

결괏값 1이 잘 나왔나요?

왜 2가 아닌지는 이전 시간인 문자열 시간에 배워서 아실 것이라 생각합니다.

모든 인덱스는 0부터 시작한다는 것을 기억해 주세요!

 

 

 

다음은 삽입입니다.

삽입과 추가는 뭐가 다를까요?

 

리스트에서 '추가'는 append를 의미하고, append는 항상 리스트의 가장 마지막에 원소를 추가합니다.

그렇기 때문에 앞서 stations이라는 변수에 역 2개를 추가하니, "사당"역 뒤로 역들이 추가됐죠?

 

 

반면 '삽입'은 원하는 위치에 값을 추가할 수 있어요.

그럼 강남역을 2번째 인덱스에 삽입해 봐요.

 

stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

stations.insert(2, "강남")

print(stations)

 

 

어떤가요? 원하는 대로 결괏값이 나왔나요?

 

맨 마지막 print문을 실행한 결괏값은 ['사당', '신도림', '강남', '인천공항']  입니다.

정말 2번째 인덱스에 강남역이 추가된 것을 알 수 있어요.

 

 

그럼 마지막으로 삭제를 알아보죠.

 

책에서는 pop을 활용한 삭제를 소개했어요.

pop은 append와 마찬가지로 맨 마지막 원소를 제거하는 메서드입니다.

 

 

한번 맨 마지막 원소인 인천공항을 제거해볼까요?

 

    
stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

stations.insert(2, "강남")

print(stations)

stations.pop()
print(stations)

 

어때요? 인천공항이 정말 삭제됐죠?

 

이렇게 배열은 원소를 추가,삽입, 삭제 할 때마다 크기가 자유자재로 변하는 성질을 가지고 있어요.

 

 

🥕멘토 TIP

책에서는 삭제하는 방법을 pop()과 clear()만 소개를 했지만, pop()에는 숨겨진 기능이 있고, remove()라는 함수도 있습니다.

 

먼저 pop()의 숨겨진 기능을 한번 보자면, pop의 괄호 안에 인덱스를 넣으면 해당 인덱스의 원소를 지울 수 있습니다.

한번 볼까요?

 

stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

stations.insert(2, "강남")

print(stations)

stations.pop(1)
print(stations)

 

어때요?

강남역을 추가한 이후의 결괏값은 ['사당', '신도림', '강남', '인천공항']이었는데,

stations.pop(1)을 수행한 이후 결괏값은 ['사당', '강남', '인천공항']입니다.

 

1번 원소가 사라진 것이죠!

 

그런데 여기서 주의할 점이 있습니다. pop(index) 함수는 조심해서 사용하셔야 해요.

왜냐하면 index가 만약 리스트의 크기보다 크거나 같다면 IndexError를 발생시켜요.

그렇기 때문에 주의해서 사용해 주셔야 해요.

 

 

 

remove() 메서드는 괄호 안에 인덱스가 아닌 원소가 들어갑니다.

아래처럼 말이죠

 

stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

stations.insert(2, "강남")

print(stations)

stations.pop(1)
print(stations)

stations.remove("강남")
print(stations)

 

결과를 확인하시면 "강남"역이 사라진 것을 확인하실 수 있어요.

 

remove() 메서드 역시 주의해서 사용하셔야 하는데요, 원소가 리스트에 존재하지 않을 경우 ValueError를 발생시킵니다.

그래서 이 메서드 역시 주의해서 사용하셔야 해요!

 

 

3) 중복 값 확인하기

책에서는 이 전 시간 문자열에서 배운 count 함수를 사용해서 중복 값을 확인하고 있어요.

count 함수는 원소의 개수를 세는 함수였죠?

 

그럼 다시 역을 3개만 만들고 다시 실행해 볼까요?

 

stations = []
stations.append("사당")

stations.append("신도림")
stations.append("인천공항")

print(stations)

stations.append("신도림")

print(stations.count("신도림"))

 

사당, 신도림, 인천공항 3개의 역을 만든 후 신도림역을 추가했어요.

 

그리고 신도림역의 개수를 세니 몇 개가 나왔죠? 총 2개입니다.

쉽죠?

 

 

4) 리스트 정렬하기

리스트 정렬 역시 정말 쉽습니다. 

책의 예제를 따라 해보시고, 지하철 예제도 함께 해봐요. 이번엔 다른 역으로 해볼게요.

 

stations = []
stations.append("왕십리역")

stations.append("서울역")
stations.append("강남")

print(stations)

stations.sort()
print(stations)

 

결괏값을 확인하셨나요?

혹시 '문자열은 어떻게 정렬하지?'라는 궁금증이 생기지 않으셨나요?

 

파이썬은 문자열을 유니코드로 변환해서 사용합니다.

한글에는 각기 맞는 유니코드가 지정되어 있죠. 그리고 그 유니코드는 한글의 사전 순과 일치하기 때문에 이렇게 사전 순으로 정렬될 수 있는 겁니다.

 

정말인지 궁금하시다면 이런 예제도 괜찮아요.

 

    
stations = []
stations.append("강남3")

stations.append("강남2")
stations.append("강남1")

print(stations)

stations.sort()
print(stations)

 

어때요? 쉽게 정렬됐죠?

 

🥕멘토 TIP

책의 reverse() 메서드는 값을 반환하지 않는 메서드입니다.

즉, 이렇게 사용하실 수 없다는 말이죠.

 

stations = []
stations.append("강남3")

stations.append("강남2")
stations.append("강남1")

print(stations.reverse())

 

reverse() 메서드는 원본 배열을 뒤집기만 한 후 어떠한 값도 반환하지 않습니다.

그래서 뒤집힌 배열을 출력하고 싶다면 print 문을 아래에 더 추가해서 출력해야 합니다.

 

stations.append("강남3")

stations.append("강남2")
stations.append("강남1")

stations.reverse()
print(stations)

 

sort() 역시 마찬가지로 값을 반환하지 않으니까, 조심해서 사용해주시길 바라요!

 

 

만약 값을 반환하는 정렬을 사용하고 싶다면 sorted()함수를 사용하면 됩니다!

**주의** sorted()함수는 원본 리스트를 바꾸지 않아요.

 

그렇기 때문에 변수명을 그대로 사용하고 싶다면 재할당을 해줘야 합니다. 아래처럼요.

 

    
stations = []
stations.append("강남3")

stations.append("강남2")
stations.append("강남1")

stations = sorted(stations)

 

이에 대한 내용은 p.133 Note 부분에 자세히 설명되어 있어요!

 

 

5) 리스트 확장하기

리스트 확장은 책에 나온 예제를 따라 하시면 쉽게 익히실 수 있어요.

 

다만 개념을 확실히 하셔야 할 것은

 

합친 리스트를 저장하고 싶은 곳. extend(합칠 리스트)입니다.

 

반대로 생각해서 잘못되는 경우가 종종 있으니 주의해 주세요~

 

 

 

2. 딕셔너리


책에서 설명되어 있는 것처럼, 딕셔너리는 key와 value가 한 쌍을 이루고 있는 자료구조입니다.

딕셔너리는 마치 사전처럼 이루어져 있어요.

 

{"apple" : "사과", "watermelon" : "수박"} 이런 것처럼 말이죠.

 

이때 앞에 오는 "apple", "watermelon"을 key라고 부르고, "사과", "수박"을 value라고 불러요.

 

이것이 바로 딕셔너리 자료구조입니다.

딕셔너리에서 가장 중요한 것은 key 값은 중복이 불가능하다는 것입니다.

 

즉, 아래와 같은 것이 불가능하다는 것이죠.

 

{"apple" : "사과", "apple" : "파인애플"}

 

이것만 숙지하고 그럼 딕셔너리 생성, 변경/추가/삭제, 값 확인하기에 대해 알아보겠습니다.

 

 

1) 딕셔너리 생성

 

딕셔너리는 중괄호를 이용해서 간단하게 생성할 수 있어요.

한번 과일 딕셔너리를 생성해 볼까요?

 

# 빈 딕셔너리
fruits = {}

# 원소가 존재하는 딕셔너리
fruits = {"apple":"사과", "watermelon":"수박"}

 

그리고 p.135하단에 "딕셔너리는 인덱스 역할을 key가 합니다."라고 나오는 것을 볼 수 있어요.

 

그럼 fruits의 각 원소를 출력하는 코드를 작성해 보세요!

 

 

다 작성하셨다면 아래 접는 글을 펴서 확인해 보세요.

 

 

더보기
# 원소가 존재하는 딕셔너리
fruits = {"apple":"사과", "watermelon":"수박"}

print(fruits["apple"])
print(fruits["watermelon"])

 

간단하죠?

 

get으로도 사용할 수 있으니 각자 작성해보세요!

 

🥕멘토 TIP

p.136에 get 방식과 대괄호(인덱스)를 사용해서 값을 얻는 방식의 차이점을 설명하고 있어요.

차이점을 잘 숙지하시고 사용하셔야 합니다. 

 

프로그램에서는 오류를 발생시키지 않는 것이 중요하니까요!

 

 

책에서 언급한 것처럼 인덱스를 사용하고 싶다면 p.137의 "in"을 사용해서 먼저 확인하는 것도 좋은 방법입니다.

이것은 이후에 배울 if 문에서 자세하게 다룰 수 있도록 할게요.

 

 

2) 값 변경/추가/삭제하기

 

값 변경은 리스트처럼 간편하게 할 수 있어요.

리스트처럼 값 변경은 모두 대괄호를 사용해서 한다는 점 기억하시고 사용하면 됩니다!

 

값 추가와 변경은 쉽지만 삭제는 조금 생소하실 것 같은데요,

 

다음 코드처럼 작성하시면 삭제가 됩니다.

 

fruits = {"apple":"사과", "watermelon":"수박"}

del fruits["apple"]

print(fruits)

 

여기서 주의하실 점은 del 함수 역시, 반드시 key 값이 존재해야 합니다.

 

존재하지 않으면 KeyError를 발생시킵니다.

그러니 먼저 "in" 함수를 사용해서 존재를 확인하는 것이 좋겠죠?

 

3) 값 확인하기

 

값을 하나하나 key를 입력하며 확인하는 것은 매우 비효율적입니다.

특히나 딕셔너리의 key가 100개 1000개가 되었을 때는 눈으로 확인하기도 어렵죠.

 

이때는 key 값만을 모아주는 메서드와 value 값만을 모아주는 메서드를 사용하면 됩니다.

 

fruits = {"apple":"사과", "watermelon":"수박"}


print(fruits.keys()) # key값만 출력
print(fruits.values()) # value 값만 출력

print(fruits.items()) # key, value 모두 출력

 

여기서 이런 생각이 드실 수도 있습니다.

 

print(fruits)print(fruits.items())와는 뭐가 다른 것인가?

 

지금은 조금 생소한 개념일 수 있습니다.

이부분은 이후에 상세하게 다루기로 하고,

지금은 '뒤에 items()가 key와 value를 따로 사용할 수 있다' 정도만 알고 넘어가시면 될 것 같아요.

 

 

3. 튜플


튜플은 리스트와 비슷하게 생겼지만 조금 다릅니다.

리스트는 추가, 삭제, 변경이 가능했지만 튜플은 그것이 불가능합니다.

 

그럼 왜 쓰냐고요? 불변임을 표현하고 싶을 때 주로 사용한답니다. (속도가 조금 더 빠른 것도 있습니다.)

 

소괄호를 사용해서 생성합니다.

 

튜플에서 새롭게 알아가면 좋은 점은 하나, 

한줄에 여러 변수의 값을 정의할 수 있다는 것 정도 알아 두시면 좋을 것 같아요.

 

a, b, c = 10, 20, 30
print(a)
print(b)
print(c)

 

괄호를 사용하지 않아도 잘 작동한답니다.

물론, 반드시 왼쪽 변수의 개수와 오른쪽 값의 개수가 같아야 합니다.

 

 

이를 튜플 할당이라고 합니다.

 

 

4. 세트


세트(set)은 우리말로는 집합입니다.

 

세트의 특징은 다음과 같습니다.

 

* 중복을 허용하지 않는다.

* 데이터 순서를 보장하지 않는다.

* 중괄호로 정의한다.

 

간단하죠?

 

p.146 첫 번째 예제가 잘 이해가 안 가실 수 있는데, 이는 5.5 자료구조 변환하기에서 자세하게 배우니, 넘어가셔도 좋습니다.

 

세트 자료구조에서 꼭 배워갔으면 하는 것은 집합의 연산입니다.

 

책에서 소개하는 집합의 연산은 3가지가 있어요.

 

* 교집합 -> 겹치는 부분  -> A ∩ B

* 차집합 -> 겹치는 부분을 제외한 자기 자신 ->  A - B

* 합집합 -> 전체 - 겹치는 부분 -> A ∪ B or A + B - (A ∩ B)

 

책에 있는 예제를 따라 작성하면서 연산 예시를 익혀봅시다.

 

집합에서 삭제는 리스트와 비슷하게 remove를 사용합니다.

remove는 반드시 존재하는 원소를 삭제해야 합니다.

그렇지 않으면 KeyError가 발생합니다.

 

🥕멘토 TIP

& 연산자는 비트 연산자라고도 불리는 연산자로 논리연산자 "and"와 동일한 역할을 하는 연산자입니다.

다만 set 자료구조에서는 교집합을 나타내니 참고해 주세요.

 

| 연산자 역시 비트 연산자로 논리 연산자 "or"과 동일한 역할을 합니다.

다만 set 자료구조에서는 합집합을 나타내니 참고해 주세요.

 

 

 

5. 자료구조 변환하기


자료구조 변환은 사용할 일이 정말 많습니다.

 

set -> list

list -> set

list -> tuple

tuple -> list

set -> tuple

tuple -> set 

 

등등 정말 많습니다.

 

자료구조 변환은 왜 필요할까요?

 

간단한 예를 들어보자면

 

튜플로 생성한 변수에 값을 추가하고 싶은 상황이 생겼습니다.

하지만 튜플은 값을 추가할 수 없죠?

 

이때 리스트로 변경해서 값을 추가한 후 다시 튜플로 변경하는 것입니다.

혹은 리스트로 값을 받아왔는데 중복 제거가 필요하다면 set으로 바꾸는 거죠.

 

tu = (1,2,3)

li = list(tu)
li.append(4)

print(li)

tu = tuple(li)
print(tu)

 

li = [5,5,7,8]
s = set(li)
print(s)

 

간단하죠?

 

p.146에서 나온 첫 번째 예제 역시 리스트를 세트 자료구조로 형 변환 한 것으로 중복으로 제거하기 위함이죠.

 

 


이번 장에서는 파이썬의 자료구조에 대해서 알아봤어요.

자료구조는 모든 데이터 저장의 기본이기 때문에 꼭 알아두셔야합니다.

 

오늘 배운 내용을 1분 퀴즈와 복습을 통해서 다시 한번 익혀주세요!

 

 

제가 공부한 내용을 보고 궁금한 점이 있으면 댓글 남겨주세요!

확인 후 답변해 드리겠습니다.

그럼 다음 6장에서 만나요!

 

 

✅ 정리

* 리스트

    * 생성, 추가/삽입/삭제

    * 중복 값 확인, 정렬, 확장

* 딕셔너리

    * key, value 형태의 자료구조

* 튜플

    * 변경이 불가능한 자료구조

* 세트

    * 중복을 허용하지 않는 자료구조

* 자료구조 변환하기

 

반응형