KR_Dictionary - somaz94/python-study GitHub Wiki
๋์ ๋๋ฆฌ๋ ํค(Key)์ ๊ฐ(Value)์ ์์ผ๋ก ์ด๋ฃจ์ด์ง ์๋ฃํ์ด๋ค. ์ค์ํ์ ์ฌ์ ๊ณผ ๋น์ทํ๊ฒ ๋จ์ด(ํค)์ ๊ทธ ์๋ฏธ(๊ฐ)๊ฐ ์ฐ๊ฒฐ๋์ด ์๋ ํํ์ด๋ค.
# ๋์
๋๋ฆฌ ์์ฑ ๋ฐฉ๋ฒ
empty = {} # ๋น ๋์
๋๋ฆฌ
person = {'name': 'John', 'age': 30} # ๊ธฐ๋ณธ์ ์ธ ๋์
๋๋ฆฌ
scores = dict(math=90, english=85) # dict() ํจ์๋ก ์์ฑ
mixed = {
'str': 'hello', # ๋ฌธ์์ด ๊ฐ
'list': [1, 2, 3], # ๋ฆฌ์คํธ ๊ฐ
'tuple': (4, 5, 6) # ํํ ๊ฐ
}
โ Tip:
- ํค(Key)๋ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ ์๋ฃํ๋ง ๊ฐ๋ฅ
- ๊ฐ(Value)์ ๋ชจ๋ ์๋ฃํ ๊ฐ๋ฅ
- ์ค๊ดํธ
{}
๋ก ํํ
# ๋์
๋๋ฆฌ ์์
person = {'name': 'John', 'age': 30}
person['age'] = 31 # ๊ฐ ์์
person['city'] = 'Seoul' # ์๋ก์ด ์ ์ถ๊ฐ
# ๋์
๋๋ฆฌ ์ญ์
del person['age'] # ํน์ ํค-๊ฐ ์ ์ญ์
person.clear() # ๋ชจ๋ ํญ๋ชฉ ์ญ์
โ ์ฃผ์์ฌํญ:
- ์กด์ฌํ์ง ์๋ ํค๋ก ์ ๊ทผํ๋ฉด KeyError ๋ฐ์
- ๊ฐ์ ํค๊ฐ ์ค๋ณต๋๋ฉด ๋ง์ง๋ง ๊ฐ๋ง ์ ํจ
- ํค๋ก ๋ฆฌ์คํธ๋ ์ฌ์ฉํ ์ ์์ (ํํ์ ๊ฐ๋ฅ)
person = {
'name': 'John',
'age': 30,
'city': 'Seoul'
}
# ํค ๋ชฉ๋ก ์ป๊ธฐ
keys = person.keys() # dict_keys ๊ฐ์ฒด ๋ฐํ
key_list = list(person.keys()) # ๋ฆฌ์คํธ๋ก ๋ณํ
# ๊ฐ ๋ชฉ๋ก ์ป๊ธฐ
values = person.values() # dict_values ๊ฐ์ฒด ๋ฐํ
value_list = list(person.values()) # ๋ฆฌ์คํธ๋ก ๋ณํ
# ํค-๊ฐ ์ ์ป๊ธฐ
items = person.items() # dict_items ๊ฐ์ฒด ๋ฐํ
item_list = list(person.items()) # ๋ฆฌ์คํธ๋ก ๋ณํ
# ํค๋ก ๊ฐ ์ป๊ธฐ
age = person.get('age') # ํค๊ฐ ์์ผ๋ฉด ๊ฐ ๋ฐํ
age = person.get('height', 0) # ํค๊ฐ ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ ๋ฐํ
# ํค ์กด์ฌ ์ฌ๋ถ ํ์ธ
'name' in person # True
'email' in person # False
# ํญ๋ชฉ ์ถ๊ฐ/์์
person.update({'email': '[email protected]', 'age': 31}) # ์ฌ๋ฌ ํญ๋ชฉ ํ๋ฒ์ ์ถ๊ฐ/์์
# ํญ๋ชฉ ์ ๊ฑฐ
removed_value = person.pop('age') # ํค์ ํด๋นํ๋ ํญ๋ชฉ ์ ๊ฑฐ ํ ๊ฐ ๋ฐํ
random_item = person.popitem() # ๋ง์ง๋ง ํญ๋ชฉ ์ ๊ฑฐ ํ (ํค, ๊ฐ) ํํ ๋ฐํ
# ๋์
๋๋ฆฌ ๋ณต์ฌ
person_copy = person.copy() # ์์ ๋ณต์ฌ
โ ์ฃผ์ ๋ฉ์๋:
-
keys()
: ๋ชจ๋ ํค๋ฅผ dict_keys ๊ฐ์ฒด๋ก ๋ฐํ -
values()
: ๋ชจ๋ ๊ฐ์ dict_values ๊ฐ์ฒด๋ก ๋ฐํ -
items()
: ๋ชจ๋ ํค-๊ฐ ์์ dict_items ๊ฐ์ฒด๋ก ๋ฐํ -
get()
: ํค๋ก ๊ฐ์ ์์ ํ๊ฒ ๊ฐ์ ธ์ค๊ธฐ -
clear()
: ๋ชจ๋ ํญ๋ชฉ ์ญ์ -
update()
: ๋ค๋ฅธ ๋์ ๋๋ฆฌ์ ๋ด์ฉ์ ์ถ๊ฐ -
pop()
: ํค์ ํด๋นํ๋ ํญ๋ชฉ ์ ๊ฑฐ ํ ๊ฐ ๋ฐํ -
popitem()
: ๋ง์ง๋ง ํญ๋ชฉ ์ ๊ฑฐ ํ (ํค, ๊ฐ) ํํ ๋ฐํ -
copy()
: ๋์ ๋๋ฆฌ ์์ ๋ณต์ฌ
# ์ค์ฒฉ ๋์
๋๋ฆฌ
users = {
'user1': {
'name': 'John',
'age': 30,
'scores': {'math': 90, 'english': 85}
},
'user2': {
'name': 'Jane',
'age': 25,
'scores': {'math': 95, 'english': 90}
}
}
# ๋์
๋๋ฆฌ ์ํ
for key in users:
print(key, users[key])
for key, value in users.items():
print(key, value)
# ๋์
๋๋ฆฌ ๋ณํฉ
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged = {**dict1, **dict2} # Python 3.5+
# Python 3.9 ์ด์์์ ์ง์ํ๋ ๊ฐ๋จํ ๋ณํฉ ์ฐ์ฐ์
# merged = dict1 | dict2 # Python 3.9+
โ ํ์ฉ Tip:
- ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์กฐํํ ๋ ์ ์ฉ
- JSON ํ์๊ณผ ํธํ์ฑ์ด ์ข์
- ํค-๊ฐ ์์ผ๋ก ๋น ๋ฅธ ๊ฒ์ ๊ฐ๋ฅ
- ์ค์ฒฉ ๊ตฌ์กฐ๋ก ๋ณต์กํ ๋ฐ์ดํฐ ํํ ๊ฐ๋ฅ
๋์ ๋๋ฆฌ ์ปดํ๋ฆฌํจ์ (Dictionary Comprehension)์ ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์ ๊ณผ ์ ์ฌํ๊ฒ ๊ฐ๊ฒฐํ ๊ตฌ๋ฌธ์ผ๋ก ๋์ ๋๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด๋ค.
# ๊ธฐ๋ณธ ํ์
squares = {x: x**2 for x in range(6)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# ์กฐ๊ฑด์ ์ถ๊ฐ
even_squares = {x: x**2 for x in range(6) if x % 2 == 0}
# {0: 0, 2: 4, 4: 16}
# ํค-๊ฐ ๋ณํ
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}
# ์ค์ฒฉ ๋ฃจํ ์ฌ์ฉ
matrix = {(i, j): i*j for i in range(3) for j in range(3)}
# {(0, 0): 0, (0, 1): 0, (0, 2): 0, (1, 0): 0, (1, 1): 1, (1, 2): 2, (2, 0): 0, (2, 1): 2, (2, 2): 4}
# if-else ์ฌ์ฉ
status = {x: 'even' if x % 2 == 0 else 'odd' for x in range(6)}
# {0: 'even', 1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd'}
# ๋ฌธ์์ด ์ฒ๋ฆฌ
word = "hello"
char_count = {char: word.count(char) for char in word}
# {'h': 1, 'e': 1, 'l': 2, 'o': 1}
โ ๋์ ๋๋ฆฌ ์ปดํ๋ฆฌํจ์ Tip:
- ๊ฐ๋ ์ฑ์ ์ํด ๋๋ฌด ๋ณต์กํ ์ปดํ๋ฆฌํจ์ ์ ํผํ๋ ๊ฒ์ด ์ข๋ค
- ๊ธฐ์กด ๋์ ๋๋ฆฌ๋ฅผ ๋ณํํ๊ฑฐ๋ ํํฐ๋งํ ๋ ์ ์ฉํ๋ค
- ์กฐ๊ฑด๋ฌธ์ ์ถ๊ฐํ ๋๋ if ์ ์ for ์ ๋ค์ ์์น์ํจ๋ค
- ๋ณํ ๋ก์ง์ด ๋ณต์กํ ๋๋ ์ผ๋ฐ ๋ฐ๋ณต๋ฌธ์ด ๋ ๋ช ํํ ์ ์๋ค
Python 3.3 ์ด์์์๋ types
๋ชจ๋์ MappingProxyType
์ ์ฌ์ฉํ์ฌ ์ฝ๊ธฐ ์ ์ฉ ๋์
๋๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ค.
from types import MappingProxyType
original = {'a': 1, 'b': 2}
read_only = MappingProxyType(original)
# ์ฝ๊ธฐ๋ ๊ฐ๋ฅ
print(read_only['a']) # 1
# ์์ ์๋๋ ์ค๋ฅ ๋ฐ์
try:
read_only['c'] = 3
except TypeError as e:
print(e) # 'mappingproxy' object does not support item assignment
# ์๋ณธ ์์ ์ ์ฝ๊ธฐ ์ ์ฉ ๋ทฐ์๋ ๋ฐ์๋จ
original['a'] = 100
print(read_only['a']) # 100
ํค๊ฐ ์์ ๋ ๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํ๋ ๋์
๋๋ฆฌ์ด๋ค. collections
๋ชจ๋์์ ์ ๊ณตํ๋ค.
from collections import defaultdict
# ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ ์ 0 ์ฌ์ฉ
int_dict = defaultdict(int)
print(int_dict['non_existent_key']) # 0
# ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ฆฌ์คํธ ์ฌ์ฉ
list_dict = defaultdict(list)
list_dict['fruits'].append('apple')
list_dict['fruits'].append('banana')
print(list_dict['fruits']) # ['apple', 'banana']
# ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ ํจ์ ์ ์
def default_factory():
return 'default value'
custom_dict = defaultdict(default_factory)
print(custom_dict['key']) # 'default value'
# ๋จ์ด ๋น๋์ ์ธ๊ธฐ
text = "hello world hello python world python"
word_count = defaultdict(int)
for word in text.split():
word_count[word] += 1
print(dict(word_count)) # {'hello': 2, 'world': 2, 'python': 2}
์์์ ๊ฐ์๋ฅผ ์ธ๋ ํนํ๋ ๋์
๋๋ฆฌ์ด๋ค. ์ญ์ collections
๋ชจ๋์์ ์ ๊ณตํ๋ค.
from collections import Counter
# ๋ฌธ์์ด์์ ๋ฌธ์ ๋น๋ ์ธ๊ธฐ
char_count = Counter("hello world")
print(char_count) # Counter({'l': 3, 'o': 2, ' ': 1, 'h': 1, 'e': 1, 'w': 1, 'r': 1, 'd': 1})
# ๋ฆฌ์คํธ์์ ์์ ๋น๋ ์ธ๊ธฐ
fruit_basket = ['apple', 'orange', 'apple', 'banana', 'orange', 'apple']
fruit_count = Counter(fruit_basket)
print(fruit_count) # Counter({'apple': 3, 'orange': 2, 'banana': 1})
# ๊ฐ์ฅ ํํ ์์ ์ฐพ๊ธฐ
print(fruit_count.most_common(2)) # [('apple', 3), ('orange', 2)]
# ์ฐ์ ์ฐ์ฐ
counter1 = Counter(['a', 'b', 'c', 'a'])
counter2 = Counter(['a', 'd', 'e'])
print(counter1 + counter2) # Counter({'a': 3, 'b': 1, 'c': 1, 'd': 1, 'e': 1})
print(counter1 - counter2) # Counter({'b': 1, 'c': 1, 'a': 1})
Python 3.7 ์ด์ ๋ฒ์ ์์ ๋์ ๋๋ฆฌ ์์๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ํด๋์ค์ด๋ค. 3.7 ์ดํ๋ก๋ ์ผ๋ฐ ๋์ ๋๋ฆฌ๋ ์์๊ฐ ๋ณด์ฅ๋์ง๋ง, ์ถ๊ฐ ๊ธฐ๋ฅ์ด ํ์ํ ๋ ์ฌ์ ํ ์ ์ฉํ๋ค.
from collections import OrderedDict
# ์์๊ฐ ์๋ ๋์
๋๋ฆฌ ์์ฑ
ordered = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# ํญ๋ชฉ ์ด๋
ordered.move_to_end('a')
print(ordered) # OrderedDict([('b', 2), ('c', 3), ('a', 1)])
# ๋ง์ง๋ง ํญ๋ชฉ ์ ๊ฑฐ
last_item = ordered.popitem()
print(last_item) # ('a', 1)
# ์์ ๋น๊ต
od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 2), ('a', 1)])
print(od1 == od2) # False - ์์๊ฐ ๋ค๋ฆ
# ์ผ๋ฐ ๋์
๋๋ฆฌ์์๋ ์์๊ฐ ์ค์ํ์ง ์์
d1 = {'a': 1, 'b': 2}
d2 = {'b': 2, 'a': 1}
print(d1 == d2) # True - ์์๊ฐ ๋ฌ๋ผ๋ ๊ฐ์
import copy
# ์์ ๋ณต์ฌ
original = {'name': 'John', 'hobbies': ['reading', 'swimming']}
shallow_copy = original.copy() # ๋๋ dict(original)
# ๋ด๋ถ ๊ฐ๋ณ ๊ฐ์ฒด๋ ์ฐธ์กฐ ๊ณต์
shallow_copy['hobbies'].append('running')
print(original['hobbies']) # ['reading', 'swimming', 'running'] - ์๋ณธ๋ ๋ณ๊ฒฝ๋จ
# ๊น์ ๋ณต์ฌ
original = {'name': 'John', 'hobbies': ['reading', 'swimming']}
deep_copy = copy.deepcopy(original)
# ๋ด๋ถ ๊ฐ๋ณ ๊ฐ์ฒด๋ ๋ณต์ฌ
deep_copy['hobbies'].append('running')
print(original['hobbies']) # ['reading', 'swimming'] - ์๋ณธ์ ๋ณ๊ฒฝ๋์ง ์์
print(deep_copy['hobbies']) # ['reading', 'swimming', 'running']
โ ๋ณต์ฌ ๊ด๋ จ Tip:
- ๋์
๋๋ฆฌ๊ฐ ์ค์ฒฉ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง์ง ์์ผ๋ฉด
copy()
๋ฉ์๋๋ก ์ถฉ๋ถํ๋ค - ๋ด๋ถ์ ๋ฆฌ์คํธ, ๋์
๋๋ฆฌ ๊ฐ์ ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ํฌํจํ๋ค๋ฉด
copy.deepcopy()
์ฌ์ฉ - ๊น์ ๋ณต์ฌ๋ ๋ชจ๋ ์ค์ฒฉ ๊ฐ์ฒด๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋ณต์ฌํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ ๋น์ฉ์ด ๋ ๋๋ค
๋์ ๋๋ฆฌ๋ ํด์ ํ ์ด๋ธ๋ก ๊ตฌํ๋์ด ์์ด ๋น ๋ฅธ ๊ฒ์, ์ฝ์ , ์ญ์ ๊ฐ ๊ฐ๋ฅํ๋ค.
import time
import timeit
# ๋์
๋๋ฆฌ vs ๋ฆฌ์คํธ ๊ฒ์ ์ฑ๋ฅ ๋น๊ต
def dict_lookup(dictionary, key):
return dictionary.get(key)
def list_lookup(item_list, key):
for k, v in item_list:
if k == key:
return v
return None
# ๋ฐ์ดํฐ ์ค๋น
size = 10000
dict_data = {str(i): i for i in range(size)}
list_data = [(str(i), i) for i in range(size)]
# ๊ฒ์ ์๊ฐ ์ธก์
dict_time = timeit.timeit(
lambda: dict_lookup(dict_data, str(size-1)),
number=10000
)
list_time = timeit.timeit(
lambda: list_lookup(list_data, str(size-1)),
number=10000
)
print(f"๋์
๋๋ฆฌ ๊ฒ์ ์๊ฐ: {dict_time:.6f}์ด")
print(f"๋ฆฌ์คํธ ๊ฒ์ ์๊ฐ: {list_time:.6f}์ด")
print(f"๋์
๋๋ฆฌ๊ฐ ์ฝ {list_time/dict_time:.1f}๋ฐฐ ๋น ๋ฆ")
๋์ ๋๋ฆฌ ์ฐ์ฐ์ ์๊ฐ ๋ณต์ก๋๋ ๋ค์๊ณผ ๊ฐ๋ค:
์ฐ์ฐ | ํ๊ท ์๊ฐ ๋ณต์ก๋ | ์ต์ ์๊ฐ ๋ณต์ก๋ |
---|---|---|
ํค ์กฐํ | O(1) | O(n) |
ํค ์ฝ์ | O(1) | O(n) |
ํค ์ญ์ | O(1) | O(n) |
ํค ์กด์ฌ ์ฌ๋ถ ํ์ธ | O(1) | O(n) |
๋ชจ๋ ํญ๋ชฉ ์ํ | O(n) | O(n) |
โ ์ฑ๋ฅ ๊ด๋ จ Tip:
- ๋์ ๋๋ฆฌ๋ ํด์ ์ถฉ๋์ด ์ ์ ๋ ๊ฐ์ฅ ํจ์จ์ ์ด๋ค
- ํค๋ก ๋ถ๋ณ ๊ฐ์ฒด(๋ฌธ์์ด, ์ซ์, ํํ)๋ฅผ ์ฌ์ฉํด์ผ ํด์ ๊ฐ์ด ์ผ๊ด์ ์ผ๋ก ์ ์ง๋๋ค
- Python 3.6๋ถํฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ต์ ํ๋์ด ์ด์ ๋ฒ์ ๋ณด๋ค ์ฝ 20-25% ๋ ํจ์จ์ ์ด๋ค
- ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋๋ ์ ๋๋ ์ดํฐ ํํ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ ์ด๋ค
def get_user_data(user_id, cache={}):
if user_id in cache:
print(f"์บ์์์ ์ฌ์ฉ์ {user_id} ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ")
return cache[user_id]
print(f"๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ {user_id} ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ")
# ์ฌ๊ธฐ์๋ ์ค์ DB ์กฐํ ๋์ ์๋ฎฌ๋ ์ด์
data = {'id': user_id, 'name': f'User {user_id}', 'age': 20 + (user_id % 10)}
cache[user_id] = data
return data
# ์ฒซ ๋ฒ์งธ ํธ์ถ์ "๋ฐ์ดํฐ๋ฒ ์ด์ค"์์ ๊ฐ์ ธ์ด
print(get_user_data(1))
# ๋ ๋ฒ์งธ ํธ์ถ์ ์บ์์์ ๊ฐ์ ธ์ด
print(get_user_data(1))
# ์ธ์ ๋ฆฌ์คํธ๋ก ๊ทธ๋ํ ํํ
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
# ๊น์ด ์ฐ์ ํ์(DFS)
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=' ')
for neighbor in graph[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
return visited
print("DFS ํ์ ๊ฒฐ๊ณผ:", end=' ')
dfs(graph, 'A') # A B D E F C
def word_frequency(text):
# ๋ฌธ์ ๋จ์๋ก ๋ถ๋ฆฌํ๊ณ ์๋ฌธ์๋ก ๋ณํ
words = text.lower().split()
# ๋จ์ด ๋น๋์ ๊ณ์ฐ
frequency = {}
for word in words:
# ๊ตฌ๋์ ์ ๊ฑฐ
word = word.strip('.,!?;:()[]{}""\'')
if word:
frequency[word] = frequency.get(word, 0) + 1
return frequency
text = "Python is amazing. Python is a great programming language."
print(word_frequency(text))
# {'python': 2, 'is': 2, 'amazing.': 1, 'a': 1, 'great': 1, 'programming': 1, 'language.': 1}
โ ํ์ฉ ์ฌ๋ก:
- ๋ฉ๋ชจ์ด์ ์ด์ (์ด์ ๊ณ์ฐ ๊ฒฐ๊ณผ ์ ์ฅ)
- ์ค์ /ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ
- ๊ฐ์ฒด ์์ฑ ์ ์ฅ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ์ฝ๋ ํํ
- ๊ทธ๋ํ, ํธ๋ฆฌ ๋ฑ ์๋ฃ๊ตฌ์กฐ ๊ตฌํ
- JSON ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ์บ์ฑ ๋ฉ์ปค๋์ฆ
- ์ํ ๊ด๋ฆฌ