Python의 딕셔너리(dict)는 해시 가능한 _키_를 _값_에 연결하는 자료 구조로, 다른 프로그래밍 언어에서는 크기를 조절할 수 있는 해시 테이블, 해시맵, 또는 연관 배열이라고 불러요.
딕셔너리는 Python에 내장된 유일한 매핑 타입이에요.
keys는 해시 가능해야 하고 딕셔너리 전체에서 유일해야 해요.
키 타입으로는 number, str, 또는 (불변 값들로 이루어진) tuple 등이 올 수 있어요.
list, dict, set처럼 가변 자료 구조는 키가 될 수 없어요.
Python 3.7부터는 dict의 키 순서가 항목을 삽입한 순서대로 보장돼요.
values는 어떤 데이터 타입이나 구조든 될 수 있어요.
값은 얼마든지 중첩될 수 있어서, 배열의 배열, 하위 딕셔너리, 그 밖의 사용자 정의 또는 복합 자료 구조를 담을 수도 있어요.
key가 주어지면 딕셔너리는 (평균적으로) 상수 시간에 value를 가져올 수 있어요(항목 수와는 무관해요).
index 위치를 모른 채 list나 array 안에서 값을 찾는 것과 비교하면, dict는 메모리를 훨씬 많이 쓰지만 값을 훨씬 빠르게 가져올 수 있어요.
딕셔너리는 항목이 많고 자주 접근하고 갱신해야 하는 상황에서 특히 유용해요.
딕셔너리는 여러 가지 방법으로 만들 수 있어요.
fromkeys() 클래스 메서드 사용**)으로 두 딕셔너리 병합|(update) 연산자로 딕셔너리 병합dict에 항목을 하나씩 추가가장 간단한 두 가지 방법은 딕셔너리 _생성자_와 딕셔너리 _리터럴_이에요.
dict()(dict 클래스의 생성자)는 key, value 쌍을 담은 반복 가능한 객체라면 무엇이든 사용할 수 있어요.
<name>=<value> 형태의 인자 여러 개를 넘겨서 호출할 수도 있어요:
# Passing a list of key,value tuples.
>>> wombat = dict([('name', 'Wombat'),
... ('speed', 23),
... ('land_animal', True)])
{'name': 'Wombat', 'speed': 23, 'land_animal': True}
# Using key=value arguments.
>>> bear = dict(name="Black Bear",
... speed=40,
... land_animal=True)
{'name': 'Black Bear', 'speed': 40, 'land_animal': True}
dict에 관한 문서에 생성자 사용법의 다양한 변형과 옵션이 정리되어 있어요.
딕셔너리는 중괄호({})로 key : value 쌍을 감싸서 _딕셔너리 리터럴_로 직접 입력할 수도 있어요.
{} 안에 들어가는 항목은 각각 다른 줄에 놓아도 돼요:
>>> whale = {"name": "Blue Whale",
"speed": 35,
"land_animal": False}
{'name': 'Blue Whale', 'speed': 35, 'land_animal': False}
>>> wombat = {'name': 'Wombat',
'speed': 23,
'land_animal': True,
'color': 'Brindle'}
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'color': 'Brindle'}
딕셔너리는 얼마든지 중첩할 수 있어요:
animals = {
"Real" : {
"Winged" : {
"Sparrow" : {'name': 'sparrow','speed': 12, 'land_animal': True},
"Kestrel" : {'name': 'kestrel', 'speed': 15, 'land_animal': True}
},
"Legged" : {
"Wombat" : {'name': 'Wombat', 'speed': 23, 'land_animal': True},
"Black Bear": {'name': 'Black Bear', 'speed': 40, 'land_animal': True},
"Polecat" : {'name': 'Polecat', 'speed': 15, 'land_animal': True}
},
"Other" : {
"Whale" : {'name': 'Blue Whale', 'speed': 35, 'land_animal': False},
"Orca" : {'name': 'Orca', 'speed': 45, 'land_animal': False},
"Snake" : {'name': 'Python', 'speed': 25, 'land_animal': True}
}
},
"Imaginary": {
"Winged" : {
"Dragon" : {'name': 'Fire Dragon','speed': 100, 'land_animal': True},
"Phoenix" : {'name': 'Phoenix', 'speed': 1500, 'land_animal': True}
},
"Legged" : {
"Sphinx" : {'name': 'Sphinx','speed': 10, 'land_animal': True},
"Minotaur" : {'name': 'Minotaur', 'speed': 5, 'land_animal': True}
},
"Other" : {}
}
}
dict에서 값에 접근하기대괄호 안에 _키_를 넣어 딕셔너리의 value에 접근할 수 있어요.
키가 딕셔너리에 없으면 KeyError가 발생해요:
>>> bear["speed"]
40
>>> bear["color"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'color'
get(<key>, <default value>) 메서드로 항목에 접근하면 KeyError를 피할 수 있어요:
>>> bear.get("color", 'not found')
'not found'
중첩 딕셔너리의 항목에 접근하려면 대괄호를 연달아 사용해요. 해당 키가 없으면 평소처럼 KeyError가 발생해요:
# Using the animals nested dictionary.
>>> animals["Real"]["winged"]["Kestrel"]["speed"]
15
>>> animals["Imaginary"]["winged"]["Kestrel"]["speed"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Kestrel'
KeyError를 피하려면 .get()을 쓸 수 있는데, .get() 호출은 반드시 _연결_해야 해요:
# Using the animals nested dictionary.
# Note the use of parenthesis to enable placing the
# .get() calls on separate lines.
>>> (animals.get("Imaginary", {})
.get("Legged", {})
.get("Sphinx", {})
.get("Color", "I have no idea!"))
'I have no idea!'
항목의 value는 _키_에 값을 할당해서 바꿀 수 있어요:
# Assigning the value "Grizzly Bear" to the name key.
>>> bear["name"] = "Grizzly Bear"
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True}
>>> whale["speed"] = 25
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False}
새로운 key:value 쌍도 같은 방식으로 _추가_할 수 있어요:
# Adding a new "color" key with a new "tawney" value.
>>> bear["color"] = 'tawney'
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'}
>>> whale["blowholes"] = 1
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1}
<dict>.pop(<key>) 메서드로 딕셔너리 항목을 삭제할 수 있어요.
<dict>.pop()은 (key, value) 쌍을 제거하고 그 value를 반환해서 쓸 수 있게 해줘요.
<dict>.get()처럼 <dict>.pop(<key>)도 두 번째 인자(<dict>.pop(<key>, <default value>))를 받을 수 있는데, 이 인자는 key를 찾지 못했을 때 반환돼요.
덕분에 KeyError가 발생하지 않아요:
# Using .pop() removes both the key and value, returning the value.
>>> bear.pop("name")
'Grizzly Bear'
# The "name" key is now removed from the dictionary.
# Attempting .pop() a second time will throw a KeyError.
>>> bear.pop("name")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
# Using a default argument with .pop() will
# prevent a KeyError from a missing key.
>>> bear.pop("name", "Unknown")
'Unknown'
del 문으로 항목을 하나 이상 제거할 수도 있어요.
제거하려는 항목이 딕셔너리에 없으면 KeyError가 발생해요:
>>> wombat = {'name': 'Wombat',
'speed': 23,
'land_animal': True,
'color': 'Brindle',
'talent': 'Singing',
'size': 'small'}
# Remove a single entry from the dictionary.
>>> del wombat["color"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'talent': 'Singing', 'size': 'small'}
# Remove multiple entries from the dictionary.
>>> del wombat["talent"], wombat["size"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True}
# Attempting a deletion of a non-existent key raises a KeyError
>>> del wombat["number_of_legs"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'number_of_legs'
for item in dict나 while item으로 딕셔너리를 순회하면 기본적으로 _키_를 대상으로 반복해요.
같은 루프 안에서 _대괄호_를 사용하면 _값_에도 접근할 수 있어요:
>>> for key in bear:
... print((key, bear[key])) # <--This prints a tuple of (key, value).
('name', 'Black Bear')
('speed', 40)
('land_animal', True)
(key, value) 튜플을 반환하는 .items() 메서드를 쓸 수도 있어요:
# dict.items() forms (key, value tuples) that can be
# unpacked and iterated over.
>>> for key, value in whale.items():
... print(key, ":", value)
name : Blue Whale
speed : 25
land_animal : False
blowholes : 1
마찬가지로 .keys()는 keys를, .values()는 values를 반환해요.
Python 딕셔너리에 대한 자세한 설명은 공식 문서가 훌륭한 출발점이에요. W3-Schools 튜토리얼을 참고해도 좋아요.
collections 모듈은 Python의 표준 컬렉션 기반 데이터 타입(dict, set, list, tuple)에 특화된 기능을 더해줘요.
가장 유용한 딕셔너리 기반 클래스 세 가지는 이래요:
Counter는 항목을 자동으로 세고, 항목을 키로, 그 개수를 값으로 하는 dict로 돌려줘요.OrderedDict는 딕셔너리 항목의 순서를 다루는 데 특화된 메서드를 가지고 있어요.defaultdict는 딕셔너리 항목을 가져오거나 대입할 때 key를 찾지 못하면 기본값을 설정하는 팩토리 메서드를 사용해요.