Chapter 7. 딕셔너리, 튜플, 셋#
학습목표와 기대효과
학습목표
딕셔너리, 튜플, 셋 데이터 타입은 리스트와 함께 다수의 데이터를 하나의 변수에 저장할 수 있는 컨테이너 데이터 타입에 속하는 종류이다.
딕셔너리, 튜플, 셋 타입의 개념과 특징을 알아보고 활용해보자.
기대효과
다양한 데이터 타입과 그 타입이 가지고 있는 특성을 이해하여 데이터를 저장하고자 할 때 적합한 데이터 타입을 활용할 수 있다.
딕셔너리#
인덱스는 항상 정수로만 해야 할까?라는 생각을 한 번 쯤은 해본 적이 있을지도 모른다. 딕셔너리는 이러한 제약을 깨고 key를 인덱스로 사용한다.
딕셔너리의 형식은 다음과 같다.
{Key1:Value1, Key2:Value2, Key3:Value3, ...}
딕셔너리는 key와 value가 쌍(pair)으로 이루어진 자료구조이며, 중괄호 { }로 묶는다.
딕셔너리의 key로는 숫자, 문자열, 튜플 등의 데이터 타입을 사용할 수 있다.
딕셔너리의 value에는 숫자, 문자열, 리스트, 튜플, 집합, 딕셔너리까지 다양한 자료형이 들어갈 수 있다.
딕셔너리 생성#
중괄호 안에 key:value 쌍을 콤마로 나열하여 직접 생성할 수 있다.
또한 dict() 함수안에 (key, value) 쌍을 순서적으로 넣어 생성할 수 있다.
변수명 = dict()
나변수명 = {}
와 같이 쓰면 비어있는 딕셔너리를 생성한다.
dict1 = {'name':'Byun', 'phone':'010-111-2222', 'birth': '09/08', 'data':[1, 2, 3]}
dict2 = dict([('L0444.000400', '컴퓨팅기초' ), ('L0444.000500', '컴퓨팅핵심'), ('L0444.000600', '컴퓨팅응용')])
dict3 = dict()
dict4 = {}
print(dict1)
print(dict2)
print(dict3)
print(dict4)
{'name': 'Byun', 'phone': '010-111-2222', 'birth': '09/08', 'data': [1, 2, 3]}
{'L0444.000400': '컴퓨팅기초', 'L0444.000500': '컴퓨팅핵심', 'L0444.000600': '컴퓨팅응용'}
{}
{}
😄 아래 key와 value를 딕셔너리 sugang_dict로 만드시오.
key |
value |
---|---|
강좌001 |
아이유, BTS, 뉴진스 |
강좌002 |
박서준, 블랙핑크, 손흥민 |
key를 통한 value 접근(활용)#
딕셔너리의 value에 접근하기 위해서는
딕셔너리변수명[key]
를 이용한다.
dict1 = {'name':'Byun', 'phone':'010-111-2222', 'birth': '09/08', 'data':[1, 2, 3]}
print( dict1['name'] )
print( dict1['phone'] )
print( dict1['birth'] )
print( dict1['data'] )
Byun
010-111-2222
09/08
[1, 2, 3]
당연한 말이지만 key가 딕셔너리에 없으면 에러가 난다.
print( dict1['address'] )
😄 앞에서 만든 딕셔너리 sugang_dict의 강좌001의 값을 출력하시오.
😄 앞에서 만든 딕셔너리 sugang_dict의 강좌001의 값의 인덱스 2의 데이터를 출력하시오.
Insertion and modification#
딕셔너리에 아이템을 추가 또는 수정하려면
딕셔너리변수명[key] = value
와 같이 하면 된다.이때 key가 없으면 딕셔너리에 추가가 되고, key가 있으면 value가 수정이 된다.
sports = { '걷기' : 4, '조깅': 7, '수영': 9} #생성
sports['계단오르기'] = 15
print(sports)
sports['계단오르기'] = 5
print(sports)
{'걷기': 4, '조깅': 7, '수영': 9, '계단오르기': 15}
{'걷기': 4, '조깅': 7, '수영': 9, '계단오르기': 5}
😄 앞에서 만든 딕셔너리 sugang_dict에 아래 key와 value를 추가하시오.
key |
value |
---|---|
강좌003 |
유재석, 류현진 |
😄 앞에서 만든 딕셔너리 sugang_dict의 강좌001의 값에 ‘임영웅’을 추가하고 확인하시오.
딕셔너리 주요 메서드와 iteration#
사용 방법 |
의미 |
예시 sports = { ‘걷기’ : 4, ‘조깅’: 7, ‘수영’: 9} |
---|---|---|
dict.get(key) |
딕셔너리에 key가 있으면 그 key와 매핑하는 value을 반환하고 |
sports.get(‘걷기’) ➡ 4 |
dict.items() |
딕셔너리의 아이템들을 리스트 형태로 반환 |
sports.items() ➡ dict_items([(‘걷기’, 4), (‘조깅’, 7), (‘수영’, 9)]) |
dict.keys() |
딕셔너리의 모든 key를 리스트 형태로 반환 |
sports.keys() ➡ dict_keys([‘걷기’, ‘조깅’, ‘수영’]) |
dict.values() |
딕셔너리의 모든 value을 리스트 형태로 반환 |
sports.values() ➡ dict_values([4, 7, 9])) |
dict.pop(key) |
딕셔너리의 key를 찾아 제거하고 value를 반환 |
sports.pop(‘조깅’) ➡ 7 |
dict.update(dict2) |
다른 딕셔너리와 합함, 반환은 없음 |
sports.update({‘피겨’:10, ‘축구’: 10, ‘야구’: 9}) ➡ sports = {‘걷기’ : 4, ‘조깅’: 7, ‘수영’: 9, ‘피겨’: 10, ‘축구’: 10, ‘야구’: 9} |
dict.clear() |
딕셔너리의 모든 아이템을 삭제 |
sports.clear() ➡ { } |
위 테이블에서 설명한 메서드를 하나씩 실행해보자.
딕셔너리의 딕셔너리변수명[key]를 이용 시, key가 없으면 에러가 나온다고 했다. 만약 딕셔너리에 key가 없더라도 에러없이 실행시키고 싶을 때에는 dict.get(key)을 사용한다.
sports = { '걷기' : 4, '조깅': 7, '수영': 9}
print( sports.get('걷기') )
sports.get('요가')
4
또는 멤버 연산자 in을 사용하여 먼저 검색한 후 key가 있을 경우에만 가져오게 하는 것도 방법이다.
if ('조깅' in sports ):
print(sports['조깅'])
7
딕셔너리의 모든 key와 values를 가져올때는 items()를 사용한다.
sports.items()
dict_items([('걷기', 4), ('조깅', 7), ('수영', 9)])
items()는 for문에서 아래와 같이 활용할 수 있다.
for의 반복변수 each는 딕셔너리를 처음부터 끝까지 순회하면서 (key, value)와 같이 튜플형태로 가져온다.
for each in sports.items():
print(each)
('걷기', 4)
('조깅', 7)
('수영', 9)
for의 반복변수를 두 개를 쓰면 각각 변수에 key와 value를 가져온다.
for key, value in sports.items():
print(key, value)
걷기 4
조깅 7
수영 9
keys()로 딕셔너리에서 key만 가져올 수 있다.
sports.keys()
dict_keys(['걷기', '조깅', '수영'])
for key in sports.keys():
print(key)
걷기
조깅
수영
values()로 딕셔너리에서 value만 가져올 수 있다.
sports.values()
dict_values([4, 7, 9])
for value in sports.values():
print(value)
4
7
9
pop()은 딕셔너리에서 key를 제거하고 value을 반환한다.
pop하려는 key가 없으면 에러가 난다.
print(sports.pop('조깅'))
sports
7
{'걷기': 4, '수영': 9}
update(dict2)는 다른 딕셔너리와 합하여 딕셔너리를 확장시킨다.
sports.update({'피겨':10, '축구': 10, '야구': 9})
sports
{'걷기': 4, '수영': 9, '피겨': 10, '축구': 10, '야구': 9}
딕셔너리의 아이템 제거할 때에는 del 키워드를 사용할 수 있다. 또는 앞서 설명했던 pop()메서드를 사용해도 된다. 두 방법 모두 key가 없으면 에러가 난다.
clear()는 딕셔너리의 모든 아이템을 제거한다.
del sports['요가']
sports.pop('요가')
sports.clear()
😄 컴기 강좌의 수강생 명단 sugang 리스트와 학번 stdid 리스트가 주어졌을 때, ‘이름:학번’에 대하여 딕셔너리를 만드시오.
hint
두 개의 리스트에서 동시에 데이터를 하나씩 가져오는 것을 반복하고 싶다면 zip()함수로 묶어 줄 수 있다. zip(리스트 변수명1, 리스트변수명 2)
sugang = ['muzi', 'con', 'apeach', 'jay-G', 'frodo', 'neo', 'tube', 'ryan', 'choonsik']
stdid = ['2023-23345', '2023-23346', '2023-23347', '2023-23348', '2023-23349', '2023-23350', '2023-23351', '2023-23352', '2023-23353']
Output: {'muzi': '2023-23345', 'con': '2023-23346', 'apeach': '2023-23347', 'jay-G': '2023-23348', 'frodo': '2023-23349', 'neo': '2023-23350', 'tube': '2023-23351', 'ryan': '2023-23352', 'choonsik': '2023-23353'}
튜플#
튜플은 리스트와 같이 순서가 있는 아이템들의 묶음이며 괄호( )로 묶어준다. 리스트에서 사용하는 연산, 인덱싱, 슬라이싱 등 모두 동일하게 사용가능하다. 리스트와 튜플의 차이는 리스트는 가변(mutable) 특징을 가지고 있는 자료구조이고, 튜플은 불변(immutable) 특징을 가지고 있는 자료구조라는 차이
가 있다.
학번, 이름, 주민등록번호 등 변경되지 않아야 하는 데이터는 튜플 타입으로 만들기에 적합하다.
mutable vs. immutable
가변(mutable)이라는 것은 객체가 만들어진 이후에도 데이터의 추가, 삽입, 삭제, 수정이 자유로운 특징을 가진 것을 의미한다. 리스트, 집합, 딕셔너리는 mutable 특징을 가진 데이터 타입이다.
불변(immutable)이라는 것은 객체가 한번 만들어진 이후에는 데이터의 추가, 삽입, 삭제, 수정이 불가하다는 것을 의미한다. 정수, 실수, 문자열, 튜플 등은 immutable 특징을 가진 데이터 타입이다.
튜플 생성#
리스트와 마찬가지로
숫자, 문자, 리스트, 딕셔너리 등 어떠한 데이터 타입이든 다 담을 수 있는 만물박스
이다.괄호( )안에 아이템을 콤마로 나열하여 직접 생성할 수 있다.
tuple() 함수의 괄호안에 아이템들을 순서적으로 넣어 생성할 수 있다.
변수명 = tuple()
나변수명 = ()
와 같이 쓰면 비어있는 튜플을 생성한다.아이템을 하나만 가진 튜플을 생성할 때에는
변수명 = (1,)
와 같이 콤마 하나를 넣어줘야 한다. 이는 숫자 (1)로 인식하는 것을 피하기 위해서이다.
t1 = ()
t2 = (1,)
t3 = (1, 2, 3)
t4 = 1, 2, 3
t5 = ( 'a', 'b', ('ab', 'cd') )
a = {'name':'Byun', 'phone':'010-111-2222', 'birth': '09/08', 'data':[1, 2, 3]}
t6 = tuple(a.keys())
t7 = tuple()
print( t1, t2, t3, t4, t5, t6, t7, sep='\n' )
()
(1,)
(1, 2, 3)
(1, 2, 3)
('a', 'b', ('ab', 'cd'))
('name', 'phone', 'birth', 'data')
()
튜플의 인덱싱, 슬라이싱 방법은 리스트, 문자열에서와 같다. 따라서 자세한 설명은 생략한다.
print(t3[2])
print(t5[1:])
print(t6[-1])
3
('b', ('ab', 'cd'))
data
튜플 주요 메서드와 iteration#
리스트에서와는 달리 아이템의 수정, 삭제, 추가, 삽입은 불가능하다.
따라서 append(), insert(), remove(), clear(), pop(), reverse(), sort(), copy() 등의 메서드는 지원하지 않는다.
사용 방법 |
의미 |
예시 |
---|---|---|
tuple.index(item) |
tuple에서 item의 index를 반환 |
std_ID.index(‘23347’) ➡ 3 |
tuple.count(item) |
tuple에서 item의 개수를 반환 |
std_ID.count(‘23346’) ➡ 2 |
아래와 같이 쓰면, 튜플의 아이템을 수정 또는 추가하지 못하여 에러가 발생한다.
std_ID = ('23345', '23346', '23346', '23347')
std_ID[1]= '23348' #수정
std_ID[4]= '23348' #추가
index()를 통해 튜플에서 아이템의 인덱스를 얻을 수 있다.
count()를 통해 튜플에서 아이템의 개수를 얻을 수 있다.
std_ID = ('23345', '23346', '23346', '23347')
print(std_ID.index('23347'))
print(std_ID.count('23346') )
3
2
year='2023'
for item in std_ID:
print(f'{year}-{item}')
2023-23345
2023-23346
2023-23346
2023-23347
(Advanced)튜플 전달과 반환#
함수에서 return으로 값을 반환할때 여러개의 값을 컴마로 나열해서 반환하면 tuple 타입으로 반환한다.
이때 반환받은 값 각각의 항목을 변수에 할당하여 사용할 수 있다.
또한 하나의 변수에 할당하면 튜플타입으로 저장된다.
def mycal(x, y):
return x+y, x-y
a, b = mycal(100, 50)
print(f'각각의 변수에 저장: {a}, {b}')
c = mycal(200, 30)
print(f'하나의 변수에 저장하면 튜플 형태로 저장:{c}')
print(c[0], c[1])
각각의 변수에 저장: 150, 50
하나의 변수에 저장하면 튜플 형태로 저장:(230, 170)
230 170
또한 여러개의 데이터를 함수의 전달인자로 주면 함수의 매개변수는 튜플타입으로 데이터를 받는다.
여러개의 데이터를 받는 매개변수를 하나만 만들고 싶을때는 매개변수 앞에 *를 붙인다.
def myData(*data):
print(data)
myData(10,20,40,80)
(10, 20, 40, 80)
😄 컴기 강좌의 수강생 명단 sugang 리스트에 있는 학생들에게 학번을 부여하려고 한다. 학번은 2023이 공통으로 들어가고 23345부터 순서대로 시작한다. 학번리스트를 튜플타입으로 출력하시오.
sugang = ['muzi', 'con', 'apeach', 'jay-G', 'frodo', 'neo', 'tube', 'ryan', 'choonsik']
Output: ('2023-23345', '2023-23346', '2023-23347', '2023-23348', '2023-23349', '2023-23350', '2023-23351', '2023-23352', '2023-23353')
집합#
리스트에서는 index를, 딕셔너리에서는 key를 사용하여 value에 접근할 수 있었다. 그렇다면 index나 key는 반드시 필요할까?
집합(set)은 index나 key가 없다. 그렇기 때문에 순서가 없으며, 값이 중복되지 않는 특징을 가진 자료구조이다. 수학의 집합과 개념적으로 아주 비슷하다.
set 생성#
중괄호 { }안에 아이템을 콤마로 나열하여 직접 생성할 수 있다.
또한
변수명 = set()
나변수명 = {}
와 같이 쓰면 비어있는 set을 생성할 수 있다.set은 아이템의 중복을 수용하지 않기 때문에 중복을 제거할 필요가 있는 데이터라면 set으로 만들면 된다.
s1 = {'foo', 'bar', 'baz', 'foo', 'qux'}
s2 = set()
s3 = set([1,1,4,2,2,6,6,6,6,7,8,10,4,2,8,6,3])
print(s1, s2, s3, sep='\n')
{'foo', 'qux', 'baz', 'bar'}
set()
{1, 2, 3, 4, 6, 7, 8, 10}
set은 순서가 없기 때문에
인덱싱이나 슬라이싱을 할 수 없다.
s1 = {'muzi', 'con', 'apeach', 'jay-G', 'frodo', 'neo', 'tube', 'ryan', 'choonsik'}
s1[0]
s1[2:5]
set에 대해서 인덱싱 또는 슬라이싱을 해야 하거나 아이템을 추가, 삽입, 수정, 삭제, 정렬 등의 작업을 해야 할 필요가 생긴다면 list()함수나 tuple()함수로 타입을 변환하면 된다.
s1 = {'muzi', 'con', 'apeach', 'jay-G', 'frodo', 'neo', 'tube', 'ryan', 'choonsik'}
l = list(s1)
t = tuple(s1)
print( l )
print( t )
['frodo', 'con', 'tube', 'jay-G', 'neo', 'muzi', 'ryan', 'apeach', 'choonsik']
('frodo', 'con', 'tube', 'jay-G', 'neo', 'muzi', 'ryan', 'apeach', 'choonsik')
set은 순서가 없기 때문에 반복이 안된다? 아니다! 순서는 없지만 반복가능한(iterable) 데이터타입이다.
for item in s1:
print(f'kakao-{item}')
kakao-frodo
kakao-con
kakao-tube
kakao-jay-G
kakao-neo
kakao-muzi
kakao-ryan
kakao-apeach
kakao-choonsik
😄 아래의 문장에서 모든 단어의 개수와 중복되는 단어를 하나만 남겨놓고 제거한 후 남아있는 전체 단어의 개수가 몇 개인지 출력해보세요.
전체 단어의 개수: 119
유일한 단어 개수: 90
sentence= '''Miracles happen to only those who believe in them.
Think like a man of action and act like man of thought.
Courage is very important. Like a muscle, it is strengthened by use.
Life is the art of drawing sufficient conclusions from insufficient premises.
By doubting we come at the truth.
A man that has no virtue in himself, ever envies virtue in others.
When money speaks, the truth keeps silent.
In the morning of life, work; in the midday, give counsel; in the evening, pray.
Painless poverty is better than embittered wealth.
A poet is the painter of the soul.
Error is the discipline through which we advance.
Faith without deeds is useless.
Weak things united become strong.'''
(Advanced) set 주요 메서드와 iteration#
사용 방법 |
의미 |
예시 |
---|---|---|
a.union(b) or |
합집합 |
a|b ➡ {1, 3, 4, 6, 7, 8, 10} |
a.difference(b) or |
차집합 |
a-b ➡ {4, 7} |
a.intersection(b) or |
교집합 |
a&b ➡ {1} |
a.symmetric_difference(b) or |
대칭차집합 |
a^b ➡ {3, 4, 6, 7, 8, 10} |
이외에도 몇 가지 메서드가 있으니 살펴보기 바란다.
a= {1,4,7}
b={1,3,6,8,10}
a와 b의 합집합은 | 와 .union()을 통해 구할 수 있다.
print(a | b)
print(a.union(b))
{1, 3, 4, 6, 7, 8, 10}
{1, 3, 4, 6, 7, 8, 10}
a와 b의 차집합은 - 와 .difference()을 통해 구할 수 있다.
print(a-b)
print(a.difference(b))
{4, 7}
{4, 7}
a와 b의 교집합은 & 와 .intersection()을 통해 구할 수 있다.
print(a & b)
print(a.intersection(b))
{1}
{1}
a와 b의 대칭차집합은 ^ 와 .symmetric_difference()을 통해 구할 수 있다.
대칭차집합은 합집합-교집합이다.
print(a.symmetric_difference(b))
print(a ^ b)
print((a|b)-(a&b))
{3, 4, 6, 7, 8, 10}
{3, 4, 6, 7, 8, 10}
{3, 4, 6, 7, 8, 10}
😄 컴기 강좌의 수강생 명단 sugang과 S학점 명단이 리스트 s_set으로 주어졌을 때, S학점을 받지 못한 사람들의 명단 u_set을 리스트로 출력하는 코드를 작성하여라. 참여자 중 동명이인은 없고, 순서는 중요하지 않다.
sugang = ['muzi', 'con', 'apeach', 'jay-G', 'frodo', 'neo', 'tube', 'ryan', 'choonsik']
s_set = ['jay-G', 'frodo', 'tube', 'choonsik']
Output: ['ryan', 'con', 'muzi', 'apeach', 'neo']
마무리#
딕셔너리는 key와 value가 쌍(pair)으로 이루어진 자료구조이며, 중괄호 { }로 묶는다.
딕셔너리의 key로는 숫자, 문자열, 튜플(숫자,문자열,튜플만 원소로 갖고 있는) 등 불변(immutable) 데이터 타입만 사용할 수 있다.
딕셔너리의 value에는 숫자, 문자열, 리스트, 튜플, 집합, 딕셔너리까지 다양한 자료형이 들어갈 수 있다.
튜플은 순서가 있는 아이템들의 묶음이며, () 소괄호로 묶는다. immutable 데이터 타입이다.
집합은 순서가 없으며, 값이 중복되지 않는 특징을 가진다.
가변(mutable)이라는 것은 객체가 만들어진 이후에도 데이터의 추가, 삽입, 삭제, 수정이 자유로운 특징을 가진 것을 의미한다. 리스트, 집합, 딕셔너리는 mutable 특징을 가진 데이터 타입이다.
불변(immutable)이라는 것은 객체가 한번 만들어진 이후에는 데이터의 추가, 삽입, 삭제, 수정이 불가하다는 것을 의미한다. 정수, 실수, 문자열, 튜플 등은 immutable 특징을 가진 데이터 타입이다.