12. 사전(Dictionaries)




1 사전 활용법


  • 사전(Dictionary) 객체의 특징
    • 집합적 자료형
    • 자료의 순서를 정하지 않는 매핑(Mapping)형
      • 키(Key)를 이용하여 값(Value)에 접근
      • 시퀀스 자료형은 아님
    • 키와 값의 매핑 1개를 아이템(item)이라고 부름
In [1]:
member = {'basketball':5, 'soccer':11, 'baseball':9}
print member['baseball'] # 검색
9
  • 값을 저장할 시에 키를 사용
    • 키가 없다면 새로운 키와 값의 아이템이 생성
    • 키가 이미 존재한다면 그 키에 해당하는 값이 변경
In [5]:
member = {'basketball':5, 'soccer':11, 'baseball':9}
member['volleyball'] = 7 # 새로운 아이템 설정
member['volleyball'] = 6 # 변경
print member
print len(member)        # 아이템의 개수 반환 
{'soccer': 11, 'basketball': 5, 'baseball': 9, 'volleyball': 6}
4
  • 사전을 출력하면 각 아이템들이 임의의 순서로 출력된다.
  • 새로운 아이템이 들어오면 키 내용에 따라 그 순서가 달라진다.
  • 내부적으로 키 내용에 대해 해쉬(Hash) 기법을 사용
  • 키와 값 매핑에 대한 아이템을 삭제할 때에는 del과 함께 키값 명시
In [4]:
member = {'basketball':5, 'soccer':11, 'baseball':9}
del member['basketball'] # 항목 삭제
print member
{'soccer': 11, 'baseball': 9}
  • [중요] 키는 변경 불가능 (Immutable) 자료만 가능
    • 문자열, 숫자, 튜플은 가능
    • 리스트, 사전은 키가 될 수 없음
  • 반면에 사전에 입력되는 값은 임의의 객체
In [2]:
d = {}
d['str'] = 'abc'
d[1] = 4
d[(1,2,3)] = 'tuple'
d[[1,2,3]] = 'list' # 리스트는 키가 될 수 없다.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-4f2e8eb1eca7> in <module>()
      3 d[1] = 4
      4 d[(1,2,3)] = 'tuple'
----> 5 d[[1,2,3]] = 'list' # 리스트는 키가 될 수 없다.

TypeError: unhashable type: 'list'
In [3]:
d[{1:2}] = 3 # 사전은 키가 될 수 없다.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-de0c91623d77> in <module>()
----> 1 d[{1:2}] = 3 # 사전은 키가 될 수 없다.

TypeError: unhashable type: 'dict'
  • 함수 이름은 사전의 키나 값으로 사용 가능함
In [5]:
def add(a, b):
    return a + b

def sub(a, b):
    return a - b

action = {0: add, 1: sub}   # 함수 이름을 사전의 값으로 사용
print action[0](4, 5)
print action[1](4, 5)
print
action2 = {add: 1, sub: 2}  # 함수 이름을 사전의 키로 사용
print action2[add]
9
-1

1
  • 사전을 생성하는 다른 방법: 내장함수 dict() 사용
In [8]:
d = dict()
print type(d)
print 

print dict(one=1, two=2)
print dict([('one', 1), ('two', 2)])
print dict({'one':1, 'two':2})
<type 'dict'>

{'two': 2, 'one': 1}
{'two': 2, 'one': 1}
{'two': 2, 'one': 1}
In [9]:
keys = ['one', 'two', 'three']
values = (1, 2, 3)
print zip(keys, values) # zip(): 두 개의 자료를 순서대로 쌍으로 묶은 튜플들의 리스트 반환
print dict(zip(keys, values))
[('one', 1), ('two', 2), ('three', 3)]
{'three': 3, 'two': 2, 'one': 1}

2 사전 메소드


  • 사전이 지원하는 중요 메소드
    • D.keys(): 사전 D에서 키들을 리스트로 반환
    • D.values(): 사전 D에서 값들을 리스트로 반환
    • D.items(): 사전 D에서 각 아이템을 튜플형태로 가져와 리스트로 반환
  • key in D: 사전 D안에 key를 키값을 가진 아이템이 있는지 확인
In [10]:
phone = {'jack':9465215, 'jin':1111, 'Joseph':6584321}

print phone.keys() # 키의 리스트 반환
print phone.values() # 값들의 리스트 반환
print phone.items() # (키, 값)의 리스트 반환
print
print 'jack' in phone # 'jack'이 phone의 키에 포함되어 있는가?
print 'lee' in phone
['jin', 'Joseph', 'jack']
[1111, 6584321, 9465215]
[('jin', 1111), ('Joseph', 6584321), ('jack', 9465215)]

True
False
  • D2 = D.copy(): 사전 D를 복사하여 D2 사전에 할당한다.
In [11]:
phone = {'jack':9465215, 'jin':1111, 'Joseph':6584321}
p = phone # 사전 레퍼런스 복사. 사전 객체는 공유된다.

phone['jack'] = 1234 # phone을 변경하면
print phone
print p # p도 함께 변경된다.
print

ph = phone.copy() # 사전복사. 별도의 사전 객체가 마련된다.
phone['jack'] = 1111 # phone을 바꿔도
print phone
print ph # ph는 바뀌지 않는다.
{'jin': 1111, 'Joseph': 6584321, 'jack': 1234}
{'jin': 1111, 'Joseph': 6584321, 'jack': 1234}

{'jin': 1111, 'Joseph': 6584321, 'jack': 1111}
{'jin': 1111, 'Joseph': 6584321, 'jack': 1234}
  • [주의] D.copy()는 Shallow Copy를 수행한다.
In [6]:
phone = {'a': [1,2,3], 'b': 4}
phone2 = phone.copy()
print phone
print phone2
print

phone['b'] = 100
print phone
print phone2
print

phone['a'][0] = 100
print phone
print phone2
{'a': [1, 2, 3], 'b': 4}
{'a': [1, 2, 3], 'b': 4}

{'a': [1, 2, 3], 'b': 100}
{'a': [1, 2, 3], 'b': 4}

{'a': [100, 2, 3], 'b': 100}
{'a': [100, 2, 3], 'b': 4}

image

In [12]:
ph = {'jack':9465215, 'jin':1111, 'Joseph':6584321}

print ph.get('jack')  # 'jack'에 대한 값을 얻는다. ph['jack']과 같다.
print ph.get('gslee') # 'gslee'에 대한 값을 얻는다. 값이 없는 경우 None반환
9465215
None
In [11]:
ph = {'jack':9465215, 'jin':1111, 'Joseph':6584321}
print ph['gslee'] # ph['gslee']는 키가 없는 경우 예외발생
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-11-00dc298a68ec> in <module>()
      1 ph = {'jack':9465215, 'jin':1111, 'Joseph':6584321}
----> 2 print ph['gslee']     # ph['gslee']는 키가 없는 경우 예외발생

KeyError: 'gslee'
In [13]:
ph = {'jack':9465215, 'jin':1111, 'Joseph':6584321}
print ph.get('gslee', 5284) # 인수를 하나 더 제공하면 'gslee'가 없는 경우에 5284 리턴
print ph # 사전에는 변화가 없다
print 

print ph.popitem()                 # 임의의 아이템을 꺼낸다.
print ph
print

print ph.popitem()                 # 임의의 아이템을 꺼낸다.
print ph 
print

print ph.pop('jack')               # 키 값을 통해 해당 아이템을 지정하여 꺼낸다.
print ph
5284
{'jin': 1111, 'Joseph': 6584321, 'jack': 9465215}

('jin', 1111)
{'Joseph': 6584321, 'jack': 9465215}

('Joseph', 6584321)
{'jack': 9465215}

9465215
{}
In [14]:
phone = {'jack':9465215, 'jin':1111, 'Joseph':6584321}
ph = {'kim':12312, 'lee': 9090}
phone.update(ph) # 사전 phone의 내용을 ph으로 추가 갱신
print phone
print
phone.clear() # 사전의 모든 입력을 없앤다.
print phone
{'jin': 1111, 'Joseph': 6584321, 'jack': 9465215, 'kim': 12312, 'lee': 9090}

{}

3 루프를 이용한 사전 내용 참조


  • 사전의 모든 키값을 순차적으로 참조하는 방법
In [15]:
D = {'a':1, 'b':2, 'c':3}
for key in D.keys():
    print key, D[key]
a 1
c 3
b 2
  • 사전 자체를 for루프에 활용하면 키에 대한 루프가 실행된다.
In [16]:
D = {'a':1, 'b':2, 'c':3}
for key in D:
    print key, D[key]
a 1
c 3
b 2
  • 키와 값을 동시에 참조하려면 D.items()를 활용한다.
In [17]:
for key, value in D.items():
    print key, value
a 1
c 3
b 2
  • 사전에 입력된 아이템들은 일정한 순서가 없다.
  • 키값에 대한 정렬은 아이템들을 리스트로 뽑은 다음에 해당 리스트에 있는 sort() 함수를 활용한다.
In [9]:
D = {'a':1, 'b':2, 'c':3}
items = D.items()
print items
print

items.sort()
print items
print 

for k,v in items:
    print k, v
[('a', 1), ('c', 3), ('b', 2)]

[('a', 1), ('b', 2), ('c', 3)]

a 1
b 2
c 3

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일