dict = {"바나나":"노랑", "사과":"빨강", "귤":"주황"}
dict["포도"]="보라"
del dict["사과"]
for i in {"a":"에이", "b":"비"}
처럼 dictionary를 반복문으로 돌리면 i
에 어떤 값이 들어가게될까? {"a":"에이"}
와 같이 key와 value가 함께 나올 것 같기도했다. 하지만 dictionary를 반복문으로 돌리면 key만 반환한다.
for i in dict:
print(i)
> 바나나
사과
귤
만약 value를 반환하고 싶거나 key, value를 함께 반환하고 싶다면? .values()
, .items()
함수
values()
는 list의 형태로(list 타입은 아니다!!) values를 반환한다.dict_values(['노랑', '빨강', '주황'])
그렇기 때문에 list에서 for문을 돌렸던 것과 같은 방식으로 반복문을 쓰면 된다.
for i in dict.values():
print(i)
노랑
빨강
주황
dictionary 반복문에서는 기본적으로 key를 반환해주지만, key들을 반환받을 수 있는
keys()
함수도 있다.values()
함수를 썼을 때와 마찬가지로 리스트의 형식으로 key들을 반환한다.dict_keys(['바나나', '사과', '귤'])
items()
함수는 key와 value를 튜플로 반환한다.
dict_items([('바나나', '노랑'), ('사과', '빨강'), ('귤', '주황')])
튜플의 요소를 그대로 쓸 수도 있고 key와 value를 각각 쓸수도 있다.
for i in dict.items():
print(i)
('바나나', '노랑')
('사과', '빨강')
('귤', '주황')
for key,value in dict.items():
print(f'과일: {key}, 색깔: {value}')
과일: 바나나, 색깔: 노랑
과일: 사과, 색깔: 빨강
과일: 귤, 색깔: 주황
values()
, keys()
, items()
함수를 사용했을 때 결과는 리스트처럼 보였다. 하지만 type()
함수를 이용해서 type을 확인해보니 다음과 같았다.
<class 'dict_values'>
<class 'dict_keys'>
<class 'dict_items'>
왜 그냥 list를 사용하지 않고 class들을 만든 것일까? 여기에는 두가지 이유가 있다고 한다.
python2에서는 원래 list 타입으로 값을 반환했었다고 한다. 하지만 values = dict.values()
로 리스트 받아온 후에 원래의 딕셔너리의 값을 바꾸면 그 내역이 valeus
에 반영되지 않는 문제가 발생했다.
dict ={"a":1, "b":2, "c":3}
values = dict.values()
print(values)
print("===========")
dict["c"]=30
print(dict)
print(values)
[1, 3, 2]
===========
{'a': 1, 'c': 30, 'b': 2}
[1, 3, 2]
보이는 것처럼 values
를 할당하고 딕셔너리를 수정한 뒤에 values
를 다시 호출하니 딕셔너리가 업데이트 되지 않았다.
Python의 dictionary는 mutable 한 특성을 가지고 있다.
즉, dictionary 의 value 값은 call by reference 와 같은 방식으로, dictionary 값이 변경되면 그 변경 값이 참조되어 함께 변경되는 특성을 가지고 있다.
values()
를 사용하면 이러한 특성이 만족되지 않아 혼란을 줄 수 있기 때문에 list type을 쓰지 않게 된 것이라고 한다.
dict ={"a":1, "b":2, "c":3}
values = dict.values()
print(values)
print("===========")
dict["c"]=30
print(dict)
print(values)
dict_values([1, 2, 3])
===========
{'a': 1, 'b': 2, 'c': 30}
dict_values([1, 2, 30])
하지만 dict_values
를 사용하니 바로 수정된 딕셔너리가 반영된 것을 볼 수 있다.
이 외에도 메모리의 효율성의 이유도 있다는데 이건 잘 모르겠어서 generator를 공부하게되면 추가하도록 하겠다.
참고: https://bluese05.tistory.com/67
하나 이상의 딕셔너리를 이용할 때 사용된다. 만약 한 사람의 정보를 담은 딕셔너리가 있다고 생각해보자.
dic1 = {"last_name": "ban",
"first_name": "hyunlang",
"address": "seoul"
}
만약 다른 사람들의 정보도 함께 저장하고 싶을때는 각 정보를 ictionary로 표현한 후 list로 같이 합해주면 된다.
information = [
{
"last_name": "ban",
"first_name": "hyunlang",
"address": "seoul"
},
{
"last_name": "kim",
"first_name": "minji",
"address": "jeju"
}
]
이렇게 여러 dictionary들을 쉽게 묶을 수 있고 for문으로 각 dictionary를 읽어들여 원하는 로직을 실행할 수 있다.
for person in information:
print(person)
> {'last_name': 'ban', 'first_name': 'hyunlang', 'address': 'seoul'}
{'last_name': 'kim', 'first_name': 'minji', 'address': 'jeju'}
딕셔너리 리스트를 for문을 돌리면 각 dictionary가 차례대로 선택되는 것을 확인할 수 있다. 각 딕셔너리의 key, value를 각각 선택해보았다.
for person in information:
for key, value in person.items():
print(f'{key}: {value}')
> last_name: ban
first_name: hyunlang
address: seoul
last_name: kim
first_name: minji
address: jeju
만약 위의 dictionary list에서 민지(minji)라는 이름을 가진 정보만 확인하고 싶다면 어떻게 해야할까?
for person in information:
if person['first_name']=="minji":
print(person)
> {'last_name': 'kim', 'first_name': 'minji', 'address': 'jeju'}
for문을 돌려 각 딕셔너리들을 하나하나 확인봐야한다. 만약 리스트의 길이가 매우 길다면 확인하는데에 긴 시간이 소요될것이다.
Nested Dictionary를 사용하면 각 딕셔너리들을 확인해볼필요 없이 더 빠르게 원하는 정보를 찾아낼 수 있다.
Nested Dictionary는 말그대로 딕셔너리 안에 딕셔너리가 있는 모습을 하고있다.
information = {
"hyunlang": {
"last_name": "ban",
"first_name": "hyunlang",
"address": "seoul"
},
"minji": {
"last_name": "kim",
"first_name": "minji",
"address": "jeju"
}
}
아까와 같은 결과값을 갖기 위해서는 필요한 딕셔너리의 key값을 지정해주면 된다.
print(information["minji"])
> {'last_name': 'kim', 'first_name': 'minji', 'address': 'jeju'}
훨씬 더 간단하게 동일한 결과가 나온 것을 확인할 수 있다.
지금까지는 key와 value에 string type을 넣어봤었고 또한 nested dictionary에서 value에 dictionary type도 넣을 수 있다는 것을 확인했다. 가능한 다른 type에는 어떤 것들이 있는지 궁금해졌다.(참고)
Keys are unique within a dictionary while values may not be. The values of a dictionary can be of any type, but the keys must be of an immutable data type such as strings, numbers, or tuples.
딕셔너리내에서 key는 unique해야하지만 value는 unique하지 않아도 된다. 따라서 vaule에는 어느 타입이든 올 수 있지만 key자리에는 strings, numbers, tuples와 같은 immutable(변하지않는)한 data type만 올 수 있다.