Introducing Python(처음 시작하는 파이썬)
Chapter 3. 파이 채우기: 리스트, 튜플, 딕셔너리, 셋
3.1 Lists and Tuples (리스트와 튜플)
- 문자열이 문자의 시퀀스라면, 리스트와 튜플은 모든 객체에 대한 시퀀스이다.
- 각 원소는 어떤 객체도 될 수 있다.
- 리스트는 Mutable(수정 가능)하며, 튜플은 Immutable(수정 불가)하다.
3.2 Lists (리스트)
- 리스트는 Mutable하므로, 원소의 순서를 바꿀 수 있다.
- 리스트의 어느 위치에나 원소를 추가/수정/삭제할 수 있다.
- 리스트는 값의 중복을 허용한다.
3.2.1 리스트 생성하기: [ ] 또는 list()
#리스트 생성
listName = [] # Empty List
listName = list() # Empty List
weekdays = ["mon", 'tue', '''wed''']
pets = list('cat', "dog")
first_name = ['Graham', 'john', 'Terry', 'Terry', 'Michael'] # 리스트는 값의 중복을 허용한다.
3.2.2 다른 데이터 타입을 리스트로 변환하기: list()
# list() 함수를 통한 리스트화
a_tuple = ('ready', 'fire', 'aim') # tuple
list(a_tuple) # a_tuple을 리스트로 변환
# 하나의 문자열에 대해 list() 함수를 사용하면, 각 문자들을 원소로 갖는 리스트를 리턴한다.
>>> list('cat')
['c', 'a', 't']
3.2.3 [offset]으로 항목 얻기
# 대괄호를 통한 Indexing과 Slicing
marxes = ['Groucho', 'Chico', 'Harpo']
>>> print(marxes[0])
'Groucho'
>>> print(marxes[2])
'Harpo'
>>> print(marxes[-1])
'Harpo'
>>> print(marxes[:]) # 리스트에 대한 Slicing이 가능하다.
['Groucho', 'Chico', 'Harpo']
>>> print(marxes[4])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
3.2.4 리스트의 리스트
# 리스트를 원소로 갖는 리스트
small_birds = ['hummingbird', 'finch']
birds = [small_birds, 'parrot'] # small_birds는 리스트이다.
>>> print(birds)
[['hummingbird', 'finch'], 'parrot']
>>> print(birds[0])
['hummingbird', 'finch']
>>> print(birds[0][1])
finch
>>> print(birds[1])
parrot
3.2.5 [offset]으로 항목 바꾸기
small_birds = ['hummingbird', 'finch']
small_birds[1] = 'sparrow'
>>> print(small_birds[1])
sparrow
3.2.6 슬라이스로 항목 추출하기
marxes = ['Groucho', 'Chico', 'Harpo']
>>> print(marxes[0:2])
['Groucho', 'Chico']
>>> print(marxes[::-2])
['Harpo', 'Groucho']
>>> print(marxes[::-1])
['Harpo', 'Chico', 'Groucho']
3.2.7 리스트의 끝에 항목 추가하기: append()
# append() 함수 : 리스트의 끝에 새 항목을 추가 (Push 연산)
List.append(item) # item이 리스트인 경우, 리스트 통째로 원소로 들어가게 됨
>>> marxes = ['Groucho', 'Chico', 'Harpo']
>>> others = ['Gummo', 'Karl']
>>> marxes.append(others)
>>> print(marxes)
['Groucho', 'Chico', 'Harpo', ['Gummo', 'Karl']] # Argument의 자료 구조를 그대로 리스트에 추가시킨다.
3.2.8 리스트 병합하기: extend() 또는 +=
# extend() 또는 += : 두 리스트를 하나의 리스트로 병합
List_1.extend(List_2) # List_1 = List_1 + List_2
List += List_2
3.2.9 오프셋과 insert()로 항목 추가하기
# insert() 함수 : 지정한 위치에 새 항목을 추가, 인덱스 범위를 넘어서면 리스트 맨 뒤에 추가
List.insert(index, value)
>>> marxes = ['Groucho', 'Chico', 'Harpo']
>>> marxes.insert(15, 'Gummo')
>>> print(marxes)
['Groucho', 'Chico', 'Harpo', 'Gummo']
>>> marxes.insert(1, 'Lee')
>>> print(marxes)
['Groucho', 'Lee', 'Chico', 'Harpo', 'Gummo']
3.2.10 오프셋으로 항목 삭제하기: del
# del 연산자 (Python의 고유한 Syntax이며, Function이 아니다.)
# 리스트에서 지정한 위치의 항목을 제거하고 뒤따르는 원소들을 한 칸씩 앞당긴다.
# 할당 연산(=)과 정반대 작용
del List[index]
>>> marxes = ['Groucho', 'Chico', 'Harpo']
>>> del marxes[-1]
>>> print(marxes)
['Groucho', 'Chico']
3.2.11 값으로 항목 삭제하기: remove()
# remove() : 리스트에서 지정한 값과 일치하는 원소를 제거하고, 뒤따르는 원소들을 한 칸씩 앞당김
List.remove(value)
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> marxes.remove('Gummo')
>>> print(marxes)
['Groucho', 'Chico', 'Harpo', 'Zeppo']
3.2.12 오프셋으로 항목을 얻은 후 삭제하기: pop()
# pop() : 리스트에서 지정한 위치의 항목을 리턴함과 동시에 제거하고 뒤따르는 원소들을 한 칸씩 앞당김
List.pop(index) # index의 default는 -1이다.
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> marxes.pop()
'Zeppo'
>>> marxes.pop(1)
'Chico'
>>> print(marxes)
['Groucho', 'Harpo', 'Gummo']
* LIFO 구조의 Stack
\(\texttt{append() - pop()}\)
* FIFO 구조의 Queue
\(\texttt{append() - pop(0)}\)
3.2.13 값으로 항목 오프셋 찾기: index()
# index() : 지정한 값에 해당하는 원소의 인덱스를 리턴
List.index(value)
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> marxes.index('Chico')
1
3.2.14 존재여부 확인하기: in
# in 연산자 (Python Syntax) : 리스트에서 지정한 값에 해당하는 원소가 존재하면 True를 리턴
item in List
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> 'Chico' in marxes
True
>>> 'Lee' in marxes
False
3.2.15 값 세기: count()
# count() : 리스트에 특정 값이 몇 개 들어있는지를 리턴
List.count(value)
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> marxes.count('Harpo')
1
>>> marxes.count('Lee')
0
>>> snl_skit = ['cheeseburger', 'cheeseburger', 'cheeseburger']
>>> snl_skit.count('cheeseburger')
3
3.2.16 문자열로 변환하기: join()
# join() : 문자열의 시퀀스를 특정 문자를 delimiter로 하여 하나의 문자열로 합침
# join()은 근본적으로 '문자열'의 메서드이므로, 주체가 되는 객체는 리스트가 아닌, 문자열이다.
>>> marxes = ['Groucho', 'Chico', 'Harpo']
>>> ', '.join(marxes)
'Groucho, Chico, Harpo'
- join()의 argument로는 문자열 또는 Iterable한 문자열의 시퀀스가 가능하다.
* split() = join()의 정반대의 기능을 하는 메서드이다.
3.2.17 정렬하기: sort()
# sort() : 리스트 자체를 내부적으로 오름차순으로 정렬
List.sort()
List.sort(reverse=True) # 내림차순 정렬
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> marxes.sort()
>>> print(marxes)
['Chico', 'Groucho', 'Gummo', 'Harpo', 'Zeppo']
# sorted() : 오름차순으로 정렬된 리스트의 "복사본"을 리턴
List_2 = List_1.sorted()
>>> marxes = ['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
>>> sorted_marxes = sorted(marxes)
>>> print(sorted_marxes)
['Chico', 'Groucho', 'Gummo', 'Harpo', 'Zeppo']
>>> print(marxes)
['Groucho', 'Chico', 'Harpo', 'Gummo', 'Zeppo']
3.2.18 항목 개수 얻기: len()
# len() : 리스트의 항목 수를 리턴
len(List)
3.2.19 할당: =, 복사: copy()
# = 연산자 : 리스트를 참조 방식으로 할당
# = 연산자를 통해 여러 변수에 할당하였다면, 한 변수에서 수정을 진행해도 원본 데이터에 반영됨
variable = List
# copy() : 리스트의 복사본을 변수에 할당
List_2 = List_1.copy()
List_2 = list(List_1) # 논리적으로 같은 동작
List_2 = List_1[:] # 논리적으로 같은 동작
>>> a = [1, 2, 3]
>>> print(a)
[1, 2, 3]
>>> b = a
>>> print(b)
[1, 2, 3]
>>> a[0] = 'modified'
>>> print(a)
['modified', 2, 3]
>>> print(b)
['modified', 2, 3]
※ List Assignment 시에는 Call by Reference 타입으로 수행된다.
- Call by Value 타입의, List의 복사본은 \(\texttt{copy()}\) 메서드를 통해 리턴받을 수 있다.
3.3 Tuples (튜플)
- Immutable한 리스트이다.
- 상수의 리스트라 할 수 있다.
- Immutable한 탓에, 멤버 함수의 수가 리스트에 비해 적다.
- 일반적으로, 튜플보다 리스트 혹은 딕셔너리 구조가 더 많이 쓰인다.
* Tuple Unpacking
- 튜플을 여러 변수에 할당하는 것을 의미한다.
- 두 객체에 대한 Swap을 구현하기에 용이하다.
# Tuple Unpacking
>>> marx_tuple = ('A', 'B', 'C')
>>> a, b, c = marx_tuple # Tuple Unpacking
>>> print(a)
A
>>> print(b)
B
>>> print(c)
C
# 할당받을 변수의 수와 튜플의 원소의 수가 일치하지 않으면 Exception을 발생시킨다.
>>> a, b, c, d = marx_tuple
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 4, got 3)
>>> marx_tuple = ('A', 'B', 'C')
>>> a, b = marx_tuple
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
# Tuple Unpacking을 이용한 Swap
>>> First = 'abc'
>>> Second = 'def'
>>> First, Second = Second, First
>>> print(First)
def
>>> print(Second)
abc
3.3.1 튜플 생성하기: ( )
>>> empty_tuple = () # 빈 튜플을 정의할 수 있다.
>>> print(empty_tuple)
()
>>> one_marx = 'Groucho', # 하나의 원소를 갖는 튜플을 정의할 경우, 원소 뒤에 Comma를 명시한다.
>>> print(one_marx)
('Groucho',)
>>> marx_tuple = 'Groucho', 'Chico', 'Harpo'
# 다수의 원소를 갖는 튜플을 정의할 경우에는 맨 뒤 원소에 Comma를 붙일 필요가 없다.
>>> print(marx_tuple)
('Groucho', 'Chico', 'Harpo')
※ 튜플 정의 시, 소괄호가 필수사항은 아니다. (하지만, 가독성을 위해 소괄호 사용이 권장된다.)
- 원소들을 Comma(",")로 구분하고, 명시적으로 소괄호를 사용함으로써 튜플임을 강조할 수 있다.
※ 원소가 하나일 경우, 원소 뒤에 Comma를 붙여야 한다 (인터프리터에게 튜플임을 인식시키기 위해서이다.)
- 원소가 다수일 경우, 마지막 원소 뒤에 Comma를 붙이지 않는다.
\(\texttt{tuple()}\) : 객체를 튜플로 만들어 리턴한다.
>>> marx_list = ['Groucho', 'Chico', 'Harpo'] # 리스트로 선언된 marx_list
>>> tuple(marx_list)
('Groucho', 'Chico', 'Harpo') # 튜플화
3.3.2 튜플과 리스트
※ 튜플의 특징
- 튜플은 메모리 효율성이 좋다.
- Immutable하므로, 프로그래머의 실수로 원소가 훼손될 우려가 없다.
- 딕셔너리의 키로 활용될 수 있다.
- Named Tuple*은 객체의 단순한 대안이 된다.
- 함수의 인자들은 튜플로써 전달된다.
* Named Tuple: Tuple의 Subclass이다. 이름(.name)과 오프셋([offset])으로 값에 접근할 수 있게 한다.
3.4 Dictionaries (딕셔너리)
- Value와 그에 대응되는 Key로 구성된 Pair가 하나의 원소가 된다. (Key : Value)
- 딕셔너리는 중괄호("{ }")로 표현된다.
- 항목의 순서를 따지지 않기 때문에 오프셋(인덱스)으로 원소를 선택할 수 없다.
- 오프셋 개념 대신, Value에 상응된 고유한(유일한) Key 값으로 데이터를 지정(선택)한다.
- Key의 순서는 임의적이다.
- Key는 보통 문자열로 표현하며, Immutable한 객체는 무엇이든 Key로써 사용이 가능하다.
※ 리스트, 딕셔너리 → Mutable
※ 튜플 → Immutable
※ 딕셔너리의 Key는 Immutable 해야 하므로, 리스트, 딕셔너리, 셋은 딕셔너리의 Key가 될 수 없다.
- Immutable한 튜플은 딕셔너리의 Key가 될 수 있다.
※ 딕셔너리 = Associative Array(연관 배열) = Hash(해쉬) = Hashmap(해쉬맵)
- 특히, Python에서 딕셔너리는 "Dict"라 부르기도 한다.
* Python 자료구조들의 Indexing 방법
- 리스트, 튜플 → [ offset ]
- 딕셔너리 → [ key ]
3.4.1 딕셔너리 생성하기: { }
# 빈 딕셔너리 정의
empty_dict = {}
# 키:데이터 pairs로 구성된 딕셔너리 정의
dict_1 = {key1:value1, key2:value2, ...}
3.4.2 딕셔너리로 변환하기: dict()
# dict() 함수 : 두 값이 한 쌍으로 이루어진 시퀀스(리스트, 튜플)를 딕셔너리로 변환함
# 시퀀스의 앞의 값은 Key, 뒤의 값은 Value로 변환한다.
Alpha = [['a', 'b'], ['c', 'd'], ['e', 'f']]
dict_1 = dict(Alpha) # 'a', 'c', 'e'는 key로, 'b', 'd', 'f'는 value로 저장
>>> Alpha = [['a', 'b'], ['c', 'd'], ['e', 'f']]
>>> dict_1 = dict(Alpha)
>>> print(dict_1)
{'a': 'b', 'c': 'd', 'e': 'f'}
Beta = ('ab', 'cd', 'ef')
dict_2 = dict(Beta) # 'c':'d', 'a':'b', 'e':'f'로 저장
>>> Beta = ('ab', 'cd', 'ef')
>>> dict_2 = dict(Beta)
>>> print(dict_2)
{'a': 'b', 'c': 'd', 'e': 'f'}
3.4.3 항목 추가/변경하기: [key]
# Dictionary Indexing
>>> python = {
... 'Chapman':'Graham',
... 'Cleese':'John',
... 'Idle':'Eric',
... 'Jones':'Terry',
... 'Palin':'Michael'
... }
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael'}
>>> python['Gilliam'] = 'Gerry'
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael', 'Gilliam': 'Gerry'}
>>> python['Gilliam'] = 'Terry'
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael', 'Gilliam': 'Terry'}
- 해당 Key가 이미 딕셔너리 내에 존재하는 경우, 새로운 Value로 대체된다.
- 해당 Key가 딕셔너리에 없는 경우, 새로운Key:Value Pair가 딕셔너리에 삽입된다.
(딕셔너리는 데이터 Pair를 순서에 상관없이 저장함을 상기하자.)
※ 딕셔너리 내의 Key는 Unique(유일)해야 한다.
3.4.4 딕셔너리 결합하기: update()
# update() : 딕셔너리 결합
dict_1.update(dict_2) # 두 딕셔너리에 키가 중복되는 경우, dict_2의 키로 overwrite 됨
3.4.5 키와 del로 항목 삭제하기
# del 연산자
# [key]에 해당하는 Key:Value Pair를 딕셔너리 내에서 삭제한다.
del dict[key]
3.4.6 모든 항목 삭제하기: clear()
# clear() 함수 : 딕셔너리의 모든 Pairs를 삭제함
dict.clear()
dict = {} # 논리적으로 같은 동작
3.4.7 in 으로 키 멤버십 테스트하기
# in 연산자 : 딕셔너리에 해당 키가 존재하면 True를 리턴, 아니면 False를 리턴함
key in dict
3.4.8 항목 얻기: [key]
# [ ] 연산자 혹은 get() 함수 : 지정한 key에 해당하는 value를 리턴함
a = dict[key] # 키가 존재하지 않으면 예외 처리
b = dict.get(key, optionValue) # 키가 존재하지 않을 경우, optionValue를 출력함
b = dict.get(key) # 옵션값을 지정하지 않은 상태에서 매칭되는 키가 존재하지 않으면, None을 리턴함 (아무것도 출력되지 않음)
- 즉, get() 함수는 결과를 리턴하기 위해, 딕셔너리에 대한 검증을 수행한다.
3.4.9 모든 키 얻기: keys()
# keys() 함수 : 딕셔너리의 모든 키를 리턴
dict_1.keys() # dict_1의 key는 'a', 'b', 'c'가 존재한다 가정
# 출력 : dict_keys(['a', 'b', 'c'])
# Python 2에서의 keys() : 딕셔너리의 키들을 리스트로 리턴
# Python 3에서의 keys() : 딕셔너리의 iterable한 키들을 보여주는 dict_keys()를 리턴
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael', 'Gilliam': 'Terry'}
>>> python.keys()
dict_keys(['Chapman', 'Cleese', 'Idle', 'Jones', 'Palin', 'Gilliam'])
3.4.10 모든 값 얻기: values()
# values() 함수 : 딕셔너리의 모든 값을 리턴
dict_1.values() # 딕셔너리의 값들을 리스트 형태로 리턴
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael', 'Gilliam': 'Terry'}
>>> python.values()
dict_values(['Graham', 'John', 'Eric', 'Terry', 'Michael', 'Terry'])
3.4.11 모든 쌍의 키-값 얻기: items()
# items() 함수 : 딕셔너리의 모든 쌍의 키-값 튜플들을 원소로 갖는 리스트를 리턴
dict.items()
>>> print(python)
{'Chapman': 'Graham', 'Cleese': 'John', 'Idle': 'Eric', 'Jones': 'Terry', 'Palin': 'Michael', 'Gilliam': 'Terry'}
>>> python.items()
dict_items([('Chapman', 'Graham'), ('Cleese', 'John'), ('Idle', 'Eric'), ('Jones', 'Terry'), ('Palin', 'Michael'), ('Gilliam', 'Terry')])
3.4.12 할당: =, 복사: copy()
# = 연산자 : 딕셔너리를 참조 방식으로 할당함
# 여러 변수에 할당되었다면, 한 변수에서 수정을 진행해도 전체에 반영됨
variable = dict
# copy() : 리스트의 복사본을 변수에 할당
List_2 = dict.copy()
3.5 Sets (셋)
- Value는 제거되고 Key만 남은 딕셔너리와 같은 구조이다.
- 딕셔너리와 같이 각각의 Key는 유일하며, 셋 또한 항목들 간 순서가 없다.
- Set은 어떤 Key가 존재하는지 여부만 판단하기 위한 상황에 적합하다.
- 아무 항목도 존재하지 않는 셋을 "null" 혹은 "empty set"이라고 한다.
3.5.1 셋 생성하기: set() 혹은 { }
# { } 연산자 혹은 set() : 셋 생성
set_1 = set(1, 2, 3)
set_2 = {4, 5, 6}
dict_1 = {} # 빈 중괄호는 빈 딕셔너리를 생성임에 유의하자!
# 중복된 Key는 하나만 저장된다.
>>> example_set = {1, 2, 2, 3}
>>> print(example_set)
{1, 2, 3}
- 중괄호("{ }")에 Key만 명시해놓은 형태가 Set이다.
- Set = Dict - Value
3.5.2 데이터 타입 변환하기: set()
# set(object) : object를 Set으로 변환한다.
>>> set( ('Ummagumma', 'Echoes', 'Atom Heart Mother') )
{'Ummagumma', 'Atom Heart Mother', 'Echoes'}
# 딕셔너리에 set()을 적용하면 Key만 저장하고, Value는 버린다.
>>> set({'apple':'red', 'orange':'orange', 'cherry':'red'})
{'cherry', 'orange', 'apple'}
3.5.3 in 으로 값 멤버십 테스트하기
# in 연산자 : 해당 셋 안에 지정된 키가 존재하면 True를 리턴
key in set
>>> drinks = {
... 'martini': {'vodka', 'vermouth'},
... 'black russian': {'vodka', 'kahlua'},
... 'white russian': {'cream', 'kahlua', 'vodka'},
... 'manhattan': {'rye', 'vermouth', 'bitters'},
... 'screwdriver': {'orange juice', 'vodka'}
... }
>>> for name, contents in drinks.items():
... if 'vodka' in contents:
... print(name)
...
martini
black russian
white russian
screwdriver
3.5.4 콤비네이션 연산자
- & 연산자혹은 intersection() 함수 : 집합 간 교집합 결과 리턴
# & 연산자 : set intersection Op (교집합 연산자)
set_1 & set_2 # set_1와 set_2에 공통으로 포함된 key들을 담은 set을 리턴
# 교집합이 없다면 empty set(False)를 리턴
set_1.intersection(set_2) # 논리적으로 같은 동작
>>> a = {1, 2}
>>> b = {2, 3}
>>> a & b
{2}
>>> a.intersection(b)
{2}
- | 연산자 혹은 union() 함수 : 집합 간 합집합 결과 리턴
# | 연산자 혹은 union() 함수 : set union Op (합집합 연산자)
set_1 | set_2 # 합집합에 포함된 key들을 담은 set을 리턴
>>> a = {1, 2}
>>> b = {2, 3}
>>> a | b
{1, 2, 3}
>>> a.union(b)
{1, 2, 3}
- 연산자 혹은difference() 함수 : 집합 간 차집합 결과 리턴
# - 연산자 혹은 difference() 함수 : set difference Op (차집합 연산자)
set_1 - set_2
set_1.difference(set_2) # 논리적으로 같은 동작
>>> a = {1, 2}
>>> b = {2, 3}
>>> a - b
{1}
>>> a. difference(b)
{1}
^ 연산자 혹은 symmetric_difference() 함수 : 집합 간 대칭차집합 결과 리턴
# ^ 연산자 혹은 symmetric_difference() 함수 : set exclusive Op (대칭 차집합 연산자)
set_1 ^ set_2
set_1.symmetric_difference() # 논리적으로 같은 동작
>>> a = {1, 2}
>>> b = {2, 3}
>>> a ^ b
{1, 3}
>>> a.symmetric_difference(b)
{1, 3}
<= 연산자 혹은 issubset() 함수 : subset 여부 리턴
# <= 연산자 혹은 issubset() 함수 : a가 b의 subset(부분집합)이면 True를 리턴
a <= b # 여기서 a, b는 set임
a.issubset(b) # 논리적으로 같은 동작
>>> a = {1, 2}
>>> b = {1, 2, 3, 4}
>>> a <= b
True
>>> b <= a
False
>>> a.issubset(b)
< 연산자 : proper subset 여부 리턴
# < 연산자 : a가 b의 proper subset(진부분집합)이면 True를 리턴
a < b
>>> a = {1, 2}
>>> b = {1, 2, 3, 4}
>>> a < b
True
>>> b < a
False
>= 연산자 혹은 issuperset() 함수 : superset 여부 리턴
# >= 연산자 혹은 issuperset() 함수 : a가 b의 superset이면 True를 리턴
a >= b
a.issuperset(b) # 논리적으로 같은 동작
>>> a >= b
False
>>> b >= a
True
>>> a.issuperset(b)
False
>>> b.issuperset(a)
True
> 연산자 : proper superset 여부 리턴
# > 연산자 : a가 b의 proper superset이면 True를 리턴
a > b
True
>>> a > b
False
>>> b > a
True
3.6 Compare Data Structures (자료구조 비교하기)
- 리스트 : 대괄호 ("[ Value ]")
- 딕셔너리 : Key:Value Pair로 구성된 중괄호 ("{ Key : Value }")
- 튜플 : 소괄호 ("( Value, )") (소괄호는 생략할 수 있으며, 단일 원소만 존재할 경우 뒤에 Comma를 붙인다.)
- 셋 : Key로만 구성된 중괄호 ("{ Key }")
3.7 Make Bigger Data Structures (자료구조를 더 크게)
- Python의 Data Structure인 리스트, 튜플, 딕셔너리는 원소로써 서로를 포함시킬 수 있으며,
이를 이용해 대규모의 자료구조를 구현할 수 있다.
- 단, 딕셔너리의 Key는 Immutable하므로 리스트, 딕셔너리, 셋은 딕셔너리의 키가 될 수 없다.
- 튜플은 딕셔너리의 Key가 될 수 있다.
# Dict의 Key로써의 Tuple
>>> houses = {
... (44.79, -93.14, 285): 'My House',
... (38.89, -77.03, 13): 'The White House'
... }
>>> houses.items()
dict_items([((44.79, -93.14, 285), 'My House'), ((38.89, -77.03, 13), 'The White House')])
3.8 Things to Do (연습문제)
3.1 출생년도에 대한 리스트 years_list를 만들어라.
출생년도를 첫 번째 요소로 하고 1년씩 증가하는 다섯 번째 생일까지의 요소를 넣는다.
출생년도가 1980이라고 가정한다.
Sol 3.1
>>> years_list = [1980, 1981, 1982, 1983, 1984]
>>> print(years_list)
[1980, 1981, 1982, 1983, 1984]
>>> years_list = list([1980, 1981, 1982, 1983, 1984])
>>> print(years_list)
[1980, 1981, 1982, 1983, 1984]
3.2 years_list의 세 번째 생일의 년도는?
참고로 오프셋 0은 출생년도다.
Sol 3.2
>>> years_list[2]
1982
3.3 years_list 중 가장 나이가 많을 때의 년도는?
Sol 3.3
>>> years_list[-1]
1984
3.4 things 리스트를 만들어라.
이 리스트는 "mozzarella", "cinderella", "salmonella" 세 문자열을 요소로 갖는다.
Sol 3.4
>>> things = ["mozzarella", "cinderella", "salmonella"]
>>> print(things)
['mozzarella', 'cinderella', 'salmonella']
3.5 things 리스트에서 사람 이름의 첫 글자를 대문자로 바꿔서 출력하라.
그러면 리스트의 요소가 변경되나?
Sol 3.5
>>> things[0].capitalize()
'Mozzarella'
>>> print(things[0].capitalize())
Mozzarella
>>> print(things[1].capitalize())
Cinderella
>>> print(things[2].capitalize())
Salmonella
>>> print(things)
['mozzarella', 'cinderella', 'salmonella']
# 변경되지 않는다.
3.6 things 리스트의 치즈 요소를 모두 대문자로 바꿔서 출력하라.
Sol 3.6
>>> print(things[0].upper())
MOZZARELLA
3.7 things 리스트에 질병 요소가 있다면 제거한 뒤 리스트를 출력하라.
Sol 3.7
>>> things.remove("salmonella")
>>> print(things)
['mozzarella', 'cinderella']
3.8 surprise 리스트를 생성하라.
이 리스트는 "Groucho", "Chico", "Harpo" 세 문자열을 요소로 갖는다.
Sol 3.8
>>> surprise = ["Groucho", "Chico", "Harpo"]
>>> print(surprise)
['Groucho', 'Chico', 'Harpo']
3.9 surprise 리스트의 마지막 요소를 소문자로 변경하고, 단어를 역전시킨 후, 첫 글자를 대문자로 바꿔라.
Sol 3.9
>>> surprise[-1] = surprise[-1].lower()
>>> print(surprise[-1])
harpo
>>> surprise[-1] = surprise[-1][::-1]
>>> print(surprise[-1])
oprah
3.10 영어-프랑스어 사전을 의미하는 e2f 딕셔너리를 만들어라, 영어의 dog는 프랑스어 chien이고,
cat은 chat, walrus는 morse다.
딕셔너리를 출력해보라.
Sol 3.10
>>> e2f = {
... 'dog': 'chien',
... 'cat': 'chat',
... 'walrus': 'morse'
... }
>>> print(e2f)
{'dog': 'chien', 'cat': 'chat', 'walrus': 'morse'}
3.11 e2f 딕셔너리에서 영어 walrus를 프랑스어로 출력하라.
Sol 3.11
>>> e2f['walrus']
'morse'
3.12 영어-프랑스어 사전의 e2f 딕셔너리를 이용해서 프랑스어-영어 사전 f2e 딕셔너리를 만들어라.
(items 메서드 사용)
Sol 3.12
>>> f2e = {}
>>> for Eng, Fre in e2f.items():
... f2e[Fre] = Eng
...
>>> print(f2e)
{'chien': 'dog', 'chat': 'cat', 'morse': 'walrus'}
3.13 f2e 딕셔너리를 사용해서 프랑스어 chien을 의미하는 영어를 출력하라.
Sol 3.13
>>> f2e['chien']
'dog'
3.14 e2f 딕셔너리의 영어 단어 키를 출력하라.
Sol 3.14
>>> e2f.keys()
dict_keys(['dog', 'cat', 'walrus'])
3.15 이차원 딕셔너리 life를 만들어라.
최상위 키는 'animals', 'plants', 'other'다.
그리고 'animals'는 각각 'cats', 'octopi', 'emus'를 키로 하고,
키 'cats'에 대해 'Henri', 'Grumpy', 'Lucy'를 값으로 하는
또 다른 딕셔너리를 참조하고 있다.
나머지 요소는 빈 딕셔너리를 참조한다.
Sol 3.15
>>> life = {
... 'animals': {
... 'cats': [
... 'Henri', 'Grumpy', 'Lucy'
... ],
... 'octopi': {},
... 'emus': {}
... },
... 'plants': {},
... 'other': {}
... }
>>> print(life)
{'animals': {'cats': ['Henri', 'Grumpy', 'Lucy'], 'octopi': {}, 'emus': {}}, 'plants': {}, 'other': {}}
3.16 life 딕셔너리의 최상위 키를 출력하라.
Sol 3.16
>>> print(life.keys())
dict_keys(['animals', 'plants', 'other'])
3.17 life['animals']의 모든 키를 출력하라.
Sol 3.17
>>> print(life['animals'].keys())
dict_keys(['cats', 'octopi', 'emus'])
3.18 life['animals']['cats']의 모든 값을 출력하라.
Sol 3.18
>>> print(life['animals']['cats'])
['Henri', 'Grumpy', 'Lucy']
Reference: Introducing Python(처음 시작하는 파이썬) (Bill Lubanovic 저, O'Reilly, 2015)