본문 바로가기

프로그래밍/Python

파이썬(Python) 기초 Step 5. 딕셔너리(Dictionary) with Python 3.7 Version

딕셔너리(Dictionary)는 리스트와 함께 가장 많이 사용되는 데이터 스트럭쳐 중 하나입니다. 딕셔너리의 가장 큰 특징은 key, value 매핑(mapping)을 사용하여 데이터를 저장한다는 것입니다. 또한 딕셔너리는 string, list, tuple 등의 시퀀스 데이터 타입과는 다르게 순서가 없는(파이썬 3.6 이하의 버전) 데이터 타입입니다. (다만, 파이썬 3.7이상의 버전에서는 순서가 있도록 업데이트 되었습니다.) 


○ 딕셔너리 정의 방법

딕셔너리는 컬리브레이스({ })를 사용하여 정의합니다. 먼저 예시 1-1)과 같이 빈 컬리브레이스를 사용하여 딕셔너리를 정의하고, 예시 1-2)와 같이 데이터 타입을 확인해보겠습니다. 그러면 빈 컬리브레이스로 정의한 딕셔너리의 데이터 타입이 dict인 것을 알 수 있습니다.

예시 1-1)

dict_1 = {}
dict_1

결과 ▷ {}

--------------------------------------------------

예시 1-2)

dict_1 = {}
type(dict_1)

결과 ▷ dict

딕셔너리의 형식은 dict_name = {key1 : value1, key2 : value2 ....}이며, 데이터는 key : value형식입니다. 간단한 딕셔너리를 정의해보면 예시 2)와 같습니다.

예시 2)

dict_2 = {'first_name' : 'coding', 'last_name' : 'CODA'}
dict_2

결과 ▷ {'first_name' : 'coding', 'last_name' : 'CODA'}

딕셔너리를 정의하는 또 다른 방법은 dict() 컨스트럭쳐를 사용하는 것입니다. 클래스 컨스트럭쳐를 사용하여 딕셔너리를 정의하면 예시 3-1)과 같습니다. 컨스트럭쳐로 정의할 때에는 key와 value 사이에 콜론( : )을 사용하는 것이 아닌 equal 연산자( = )를 사용하며, key는 변수와 동일한 역할을 하기 때문에 따옴표로 감싸지 않습니다. 만약 key값을 따옴표로 감쌀 경우 예시 3-2)와 같이 SyntaxError가 발생하며, equal 연산자 대신 콜론을 사용하여도 예시 3-3)과 같이 SyntaxError가 발생합니다.

예시 3-1)

dict_3 = dict(first_name = 'coding', last_name = 'CODA')
dict_3

결과 ▷ {'first_name' : 'coding', 'last_name' : 'CODA'}

---------------------------------------------------------------------

예시 3-2)

dict_3 = dict('first_name' = 'coding', 'last_name' = 'CODA')
dict_3

결과 ▷ 
 File "<ipython-input-36-e5a70a34aab3>", line 1
    dict_3 = dict('first_name' = 'coding', 'last_name' = 'CODA')
                 ^
SyntaxError: keyword can't be an expression

---------------------------------------------------------------------

예시 3-3)

dict_3 = dict(first_name : 'coding', last_name : 'CODA')
dict_3

결과 ▷
  File "<ipython-input-37-ac15cfc4afba>", line 1
    dict_3 = dict(first_name : 'coding', last_name : 'CODA')
                             ^
SyntaxError: invalid syntax

딕셔너리를 정의할 때 또 다른 주의할 점은 딕셔너리를 저장할 이름으로 built-in 클래스 이름인 dict를 사용하면 dict 안에 정의된 type 오브젝트가 딕셔너리 오브젝트로 overwrite 되고 딕셔너리 컨스트럭쳐를 사용할 수 없게 되니 주의해야 합니다. 

2019/08/14 - 파이썬(Python) 기초 Step 1. 변수

딕셔너리의 데이터를 참조하거나 변경하고자 할 때에는 각 데이터의 key값을 사용하면 됩니다. 예시 4)와 같이 last_name을 사용하여 'CODA'라는 값을 출력해보겠습니다.

예시 4)

dict_4 = dict(first_name = 'coding', last_name = 'CODA')
dict_4['last_name']

결과 ▷ 'CODA'

이번에는 예시 5)와 같이 대문자인 'CODA'를 소문자인 'coda'로 변경해보도록 하겠습니다. 그러면 다음과 같이 last_name의 value값이 'CODA'에서 'coda'로 변경된 것을 볼 수 있습니다.

예시 5)

dict_5 = dict(first_name = 'coding', last_name = 'CODA')
dict_5['last_name'] = 'coda'
dict_5

결과 ▷ {'first_name': 'coding', 'last_name': 'coda'}

예시 6)과 같이 새로운 데이터를 추가하거나 삭제할 수도 있습니다. 예시 6-1)과 같이 직업을 key값인 'job'으로, value값을 'programmer'로 추가해보겠습니다. 이어서 예시 6-2)와 같이 del함수를 사용하여 방금 추가한 데이터를 삭제해보겠습니다. 이렇게 딕셔너리 안에 데이터를 참조하거나 삭제할 때 딕셔너리 안에 존재하지 않는 key값을 사용하여 참조하면 예시 6-3)과 같이 KeyError가 발생하며, 존재하지 않는 key값을 사용하여 데이터를 삭제할 경우에도 예시 6-4)와 같이  KeyError가 발생합니다.

예시 6-1)

dict_6 = dict(first_name = 'coding', last_name = 'CODA')
dict_6['job'] = 'programmer'
dict_6

결과 ▷ {'first_name': 'coding', 'last_name': 'CODA', 'job': 'programmer'}

-------------------------------------------------------------------------

예시 6-2)
dict_6 = dict(first_name = 'coding', last_name = 'CODA', job = 'programmer')
del dict_6['job']
dict_6

결과 ▷ {'first_name': 'coding', 'last_name': 'CODA'}

-------------------------------------------------------------------------

예시 6-3)

dict_6 = dict(first_name = 'coding', last_name = 'CODA')
dict_6['job']
dict_6

결과 ▷
KeyError
Traceback (most recent call last)
<ipython-input-48-4d34b9504691> in <module>
      1 dict_6 = dict(first_name = 'coding', last_name = 'CODA')
----> 2 dict_6['job']
      3 dict_6

KeyError: 'job'

-------------------------------------------------------------------------

예시 6-4)

dict_6 = dict(first_name = 'coding', last_name = 'CODA')
del dict_6['job']
dict_6

결과 ▷
KeyError
Traceback (most recent call last)
<ipython-input-49-d28e057239c6> in <module>
      1 dict_6 = dict(first_name = 'coding', last_name = 'CODA')
----> 2 del dict_6['job']
      3 dict_6

KeyError: 'job'

딕셔너리를 정의할 때 key값으로 사용 가능한 데이터 타입은 int, float, str tuple입니다. 사용 가능한 데이터 타입으로 딕셔너리를 정의해보면 예시 7-1)과 같습니다. 하지만 딕셔너리로 리스트와 딕셔너리 타입은 key값으로 사용할 수 없습니다. key값으로 사용 불가능한 리스트 타입으로 딕셔너리를 정의해보면 예시 7-2)과 같은 TypeError가 발생하며, 딕셔너리 타입으로 딕셔너리를 정의해보면 예시 7-3)과 같은 TypeError가 발생합니다. 

예시 7-1)

dict_7 = {1 : 'int', 1.23 : 'float', '123' : 'str', (1, 2, 3) : 'tuple'}
dict_7

결과 ▷ {1: 'int', 1.23: 'float', '123': 'str', (1, 2, 3): 'tuple'}

-------------------------------------------------------------------------

예시 7-2) 

dict_7 = {[1, 2, 3] : 'list'}
dict_7

결과 ▷
TypeError
Traceback (most recent call last)
<ipython-input-52-24a9b9ef111c> in <module>
----> 1 dict_7 = {[1, 2, 3] : 'list'}
      2 dict_7

TypeError: unhashable type: 'list'

-------------------------------------------------------------------------

예시 7-3)

dict_7 = {{1:1} : 'dict'}
dict_7

결과 ▷
TypeError
Traceback (most recent call last)
<ipython-input-53-dae26d75d8eb> in <module>
----> 1 dict_7 = {{1:1} : 'dict'}
      2 dict_7

TypeError: unhashable type: 'dict'

이렇게 딕셔너리의 key값에는 int, float, str, tuple 타입으로만 저장할 수 있는 반면에 딕셔너리 value에는 예시 8)과 같이 모든 데이터 타입을 저장할 수 있습니다. 

예시 8)

dict_8 = {
    'int' : 1,
    'float' : 1.23,
    'str' : 'string',
    'list' : [1, 2, 3],
    'tuple' : (1, 2, 3),
    'dict' : {'one' : 1, 'two' : 2}
}
dict_8

결과 ▷
{'int': 1,
 'float': 1.23,
 'str': 'string',
 'list': [1, 2, 3],
 'tuple': (1, 2, 3),
 'dict': {'one': 1, 'two': 2}}

딕셔너리 안의 리스트 데이터를 참조할 경우에는 dict_name['key'][index]를 입력하면 됩니다. 이번에는 예시 9-1)와 같이 예시 8)에서 정의한 딕셔너리 안에 있는 리스트에서 데이터 1을 참조해보도록 하겠습니다. 또한, 딕셔너리 안의 딕셔너리 데이터를 참조할 경우 dict_name['key']['key']를 입력하면 됩니다. 예시 9-2)와 같이 예시 8)에서 정의한 딕셔너리 안에 있는 딕셔너리에서 1을 참조해보도록 하겠습니다. 

예시 9-1)

dict_8 = {
    'int' : 1,
    'float' : 1.23,
    'str' : 'string',
    'list' : [1, 2, 3],
    'tuple' : (1, 2, 3),
    'dict' : {'one' : 1, 'two' : 2}
}
dict_8
dict_8['list'][0]

결과 ▷ 1

--------------------------------------

예시 9-2)

dict_8 = {
    'int' : 1,
    'float' : 1.23,
    'str' : 'string',
    'list' : [1, 2, 3],
    'tuple' : (1, 2, 3),
    'dict' : {'one' : 1, 'two' : 2}
}
dict_8
dict_8['dict']['one']

결과 ▷ 1

○ 딕셔너리 클래스의 메소드 사용 방법

이번에는 딕셔너리 클래스에 있는 메소드의 사용 방법에 대해 알아보겠습니다. 딕셔너리 클래스에 있는 메소드는 예시 10)과 같이 help함수를 사용하여 확인할 수 있습니다.

예시 10)

help(dict)

결과 ▷
Help on class dict in module builtins:

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)
 |  
 |  Methods defined here:
 |  
 |  __contains__(self, key, /)
 |      True if the dictionary has the specified key, else False.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D
 |  
 |  get(self, key, default=None, /)
 |      Return the value for key if key is in the dictionary, else default.
 |  
 |  items(...)
 |      D.items() -> a set-like object providing a view on D's items
 |  
 |  keys(...)
 |      D.keys() -> a set-like object providing a view on D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      If key is not found, d is returned if given, otherwise KeyError is raised
 |  
 |  popitem(...)
 |      D.popitem() -> (k, v), remove and return some (key, value) pair as a
 |      2-tuple; but raise KeyError if D is empty.
 |  
 |  setdefault(self, key, default=None, /)
 |      Insert key with a value of default if key is not in the dictionary.
 |      
 |      Return the value for key if key is in the dictionary, else default.
 |  
 |  update(...)
 |      D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
 |      If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
 |      If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
 |      In either case, this is followed by: for k in F:  D[k] = F[k]
 |  
 |  values(...)
 |      D.values() -> an object providing a view on D's values
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  fromkeys(iterable, value=None, /) from builtins.type
 |      Create a new dictionary with keys from iterable and values set to value.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

(1) clear메소드 사용 방법

clear메소드는 딕셔너리 안에 정의된 데이터를 모두 삭제하는 메소드입니다. 예시 11)과 같이 딕셔너리를 하나 정의한 후 clear메소드를 사용하여 삭제해보도록 하겠습니다.

예시 11)

dict_9 = {'one' : 1, 'two' : 2, 'three' : 3}
dict_9.clear()
dict_9

결과 ▷ {}

(2) get메소드 사용 방법

메소드에 전달된 key값이 딕셔너리에 존재하면 key값에 대한 데이터를 반환하고, key값이 존재하지 않으면 NULL을 반환합니다. 보통 존재하지 않는 key값을 참조하여 KeyError가 발생하는 것을 방지하기 위해서 자주 사용되는 메소드입니다. 예시 12-1)와 같이 딕셔너리를 정의한 후 get메소드를 사용하여 데이터를 출력해보겠습니다. 이어서 예제 12-2)에서 존재하지 않는 key값을 get메소드에 전달하겠습니다. 쥬피터 노트북을 사용하는 경우 반환되는 값이 없을 경우 어떠한 값도 출력하지 않습니다. 따라서 print함수를 사용하여 None 데이터가 반환되는지 확인해보겠습니다.

예시 12-1)

dict_10 = {'one' : 1, 'two' : 2, 'three' : 3}
dict_10.get('one')

결과 ▷ 1

----------------------------------------------

예제 12-2)

dict_10 = {'one' : 1, 'two' : 2, 'three' : 3}
print(dict_10.get('four'))

결과 ▷ None

(3) items메소드 사용 방법

파이썬 딕셔너리는 for문에서 사용할 수 있는 이터레이터 오브젝트입니다. 예시 13-1)에서 딕셔너리를 새롭게 정의하고 iter함수로 확인해보도록 하겠습니다. 결과와 같이 딕셔너리가 이터레이터 오브젝트인 것을 확인할 수 있습니다. 예시 13-2)에서는 for문을 순환하면서 데이터를 출력해보도록 하겠습니다. 딕셔너리의 데이터를 for문에서 접근하면 key값만 출력하는 것을 알 수 있습니다. 하지만 items메소드를 사용하면 예시 13-3)과 같이 key와 value가 튜플 형식으로 반환되는 것을 볼 수 있습니다. 일반적으로 items메소드를 사용하여 순환을 할 때에는 key의 값을 저장하는 변수와 value의 값을 저장하는 변수를 정의한 뒤 예시 13-4)와 같이 각각의 데이터를 따로 사용합니다. 

예시 13-1)

dict_11 = {'one' : 1, 'two' : 2, 'three' : 3}
iter(dict_11)

결과 ▷ <dict_keyiterator at 0x1b3bcfb1818>

---------------------------------------------

예시 13-2)

dict_11 = {'one' : 1, 'two' : 2, 'three' : 3}
for i in dict_11 :
	print(i)
    
결과 ▷ one
        two
        three

---------------------------------------------

예시 13-3)

dict_10 = {'one' : 1, 'two' : 2, 'three' : 3}
for i in dict_10.items() :
	print(i)
    
결과 ▷ ('one', 1)
        ('two', 2)
        ('three', 3)

---------------------------------------------

예시 13-4)

dict_10 = {'one' : 1, 'two' : 2, 'three' : 3}
for k, v in dict_10.items():
	print('key: {}, value: {}'.format(k, v))
    
결과 ▷ key: one, value: 1
        key: two, value: 2
        key: three, value: 3

(4) keys메소드 사용 방법

keys메소드는 딕셔너리에 정의된 모든 key값을 리스트 형식으로 반환합니다. keys메소드는 딕셔너리에 key값을 정렬하고 그 정렬된 순서대로 데이터에 접근하고자 할 때 많이 사용됩니다. 예시 14-1)과 같이 딕셔너리를 정의한 뒤 for문을 사용하여 출력해보겠습니다. 그러면 데이터가 정해진 순서 없이 출력된 것을 볼 수 있습니다. 이번에는 예시 14-2)에서 key값을 오름차순으로 정렬하여 출력해보도록 하겠습니다. 

예시 14-1)

dict_11 = {'b' : 2, 'a' : 1, 'c' : 3}
for i in dict_11 :
	print(dict_11[i])
    
결과 ▷ 2
        1
        3

-----------------------------------------

예시 14-2)

dict_11 = {'b' : 2, 'a' : 1, 'c' : 3}
dict_keys = dict_11.keys()
dict_keys = sorted(dict_keys)
for i in dict_keys : 
	print(dict_11[i])
    
결과 ▷ 1
        2
        3 

(5) values메소드 사용 방법

values메소드는 예시 15)와 같이 딕셔너리의 모든 value값을 리스트 형식으로 반환합니다. 

예시 15)

dict_12 = {'b' : 2, 'a' : 1, 'c' : 3}
dict_12.values()

결과 ▷ dict_values([2, 1, 3])

(6) update메소드 사용 방법

update메소드는 두 딕셔너리를 하나의 딕셔너리로 합쳐주는 메소드입니다. 예시 16)에서 두 개의 딕셔너리를 정의한 뒤 하나의 딕셔너리로 합쳐주도록 하겠습니다. 

예시 16)

dict_13 = {'key_a' : 'a', 'key_b' : 'b', 'key_c' : 'c'}
dict_14 = {'key_d' : 'd', 'key_e' : 'e', 'key_f' : 'f'}
dict_13.update(dict_14)
dict_13

결과 ▷
{'key_a': 'a',
 'key_b': 'b',
 'key_c': 'c',
 'key_d': 'd',
 'key_e': 'e',
 'key_f': 'f'}

딕셔너리의 활용 방법은 무궁무진하지만, 현재 이 포스팅은 파이썬 기초에 대한 내용을 다루기 때문에 추가적인 활용 방법은 나중에 따로 포스팅하도록 하겠습니다.