Chapter04 반복문 (4-2 딕셔너리와 반복문)

lasso·2021년 5월 14일
0

4-2 딕셔너리와 반복문

딕셔너리
4-1에서 여러 개의 값을 나타낼 수 있게 해주는 자료형으로 리스트와 딕셔너리가 있고 이들은 반복문의 in 키워드 뒤에 반복할 수 있는 것으로 넣을 수 있다고 배웠습니다. 지금까지 리스트를 살펴보았으므로, 이번 절에서는 딕셔너리에 대해 알아보겠습니다.

시작하기 전에

리스트가 인덱스를 기반으로 값을 저장하는것 이라면, 딕셔너리는 키를 기반으로 값을 저장하는 것이라고 할 수 있습니다. 다음 예를 살펴봅시다.

# 키로 문자, 숫자, 불 모두 사용 가능하지만 리스트와 딕셔너리는 키로 사용할 수 없다.
>>> dictionary = {
        "키A" : "값A",
        "키B" : "값B",
        "키C" : "값C",
        "문자열" : "값",
        123 : [1, 2, 3],
        True : False
	}
>>> print(dictionary["키A"])
#딕셔너리["키이름"] = 키가 가진 요소의 값
값A
자료형의미가리키는 위치선언 형식
리스트인덱스를 기반으로 값을 저장인덱스변수 = []
딕셔너리키를 기반으로 값을 저장변수 = []

딕셔너리 선언하기

딕셔너리는 중괄호 {}로 선언하며, '키 : 값' 형태를 쉼표(,)로 연결해서 만듭니다. 키는 문자열, 숫자, 불 등으로 선언할 수 있습니다. 하지만 일반적으로는 문자열로 사요하는 경우가 많습니다.

딕셔너리를 어떻게 생성하는지 살펴볼까요?

변수 = {:,:,
    ...:,
}

코드를 적용해 보면 좀 더 쉽게 이해할 수 있습니다.

>>> dict_a = {
        "name" : "어벤저스 엔드게임",
        "type" : "히어로 무비"
        }

딕셔너리의 요소에 접근하기

바로 앞에서 선언한 딕셔너리를 출력해 볼까요?

>>> dict_a
{'name': '어벤저스 엔드게임', 'type': '히어로 무비'}

특정 키 값만 따로 출력할 수도 있습니다. 딕셔너리의 요소에 접근할 때는 리스트처럼 딕셔너리의 요소에 접근할 때는 리스트처럼 딕셔너리 뒤에 대괄호[]를 입력하고 내부에 인덱스처럼 키를 입력합니다. 이때 주의할 점은 딕셔너리를 선언할 때는 중괄호{}를 사용하지만, 딕셔너리의 요소에 접근할 때는 리스트처럼 딕셔너리 뒤에 대괄호[]를 입력하고 내부에 인덱스처럼 키를 입력한다는 것입니다.

## 딕셔너리 요소에 접근하기
>>> dict_a["name"]
'어벤저스 엔드게임'
>>> dict_a["type"]
'히어로 무비'

딕셔너리 내부의 값에 문자열, 숫자, 불 등의 다양한 자료를 넣을 수도 있습니다. 리스트와 딕셔너리도 하나의 자료이므로, 리스트와 딕셔너리를 값으로 넣을 수도 있습니다.

>>> dict_b = {
        "director" : ["안소니 루소", "조 루소"],
        "cast" : ["아이언맨", "타노스", "토르","닥터스트레인지","헐크"]
    }

다음과 같은 결과를 확인할 수 있습니다.

>>> dict_b
{'director': ['안소니 루소', '조 루소'],
 'cast': ['아이언맨', '타노스', '토르', '닥터스트레인지', '헐크']}
 >>> dict_b["director"]
 ['안소니 루소', '조 루소']

요소에 접근하는 방법은 리스트와 거의 비슷하므로 쉽게 이해할 수 있습니다.

구분선언 형식사용 예틀린 예
리스트list_a = []list_a[1]
딕셔너리dict_a = {}dict_a["name"]dict_a{"name"}

틀린 예는 처음 파이썬을 공부할 때 자주 실수하는 형태이므로 주의해주세요.
예제를 통해 확인해 보겠습니다.

👉 딕셔너리의 요소에 접근하기

소스코드 dict01.py

# 딕셔너리를 선언합니다.
dictionary = {
    "name" : "7D 건조 망고",
    "type" : "당절임",
    "ingredient" : ["망고", "설탕", "메타중아황산나트륨", "치자황색소"],
    "origin" : "필리핀"
}

# 출력합니다.
print("name :", dictionary["name"])
print("type :", dictionary["type"])
print("ingredient :", dictionary["ingredient"])
print("origin :", dictionary["origin"])
print()

# 값을 변경합니다.
dictionary["name"] = "8D 건조 망고"
print("name :", dictionary["name"])

## 실행 결과
name : 7D 건조 망고
type : 당절임
ingredient : ['망고', '설탕', '메타중아황산나트륨', '치자황색소']
origin : 필리핀

name : 8D 건조 망고

위의 예제에서 보면 ingredient는 dictionary의 키이기도 하지만, 여러 개의 자료를 가지고 있는 리스트이기도 하므로 다음과 같이 인덱스를 지정하여 리스트 안의 특정 값을 출력할 수도 있습니다.

>>> dictionary["ingredient"]
['망고', '설탕', '메타중아황산나트륨', '치자황색소']
>>> dictionary["ingredient"][1]
'설탕'

☑️ 딕셔너리의 문자열 키와 관련된 실수

딕셔너리를 만들 때 다음과 같이 입력 실수를 하는 경우가 꽤 많습니다. 이러한 코드를 실행하면 NameError라는 오류가 발생합니다.

>>> dict_key = {
        name : "7D 건조 망고",
        type : "당절임"
    }
NameError              Traceback (most recent call last)
<ipython-input-16-8174b9414034> in <module>
      1 dict_key = {
----> 2     name : "7D 건조 망고",
      3     type : "당절임"
      4 }

NameError: name 'name' is not defined

name이라는 이름이 정의되지 않았다는 오류입니다. 파이썬은 딕셔너리의 키에 단순한 식별자를 입력하면 이를 변수로 인식합니다. 오류 자체를 해결하고 싶다면 다음과 같이 name이라는 이름을 변수로 만들어 주면 됩니다. type은 type()함수라는 기본 식별자가 있기 때문에 이것이 키로 들어가 따로 오류를 발생하지는 않습니다.

>>> name = "이름"
>>> dict_key = {
        name : "7D 건조 망고",
        type : "당절임"
    }
>>>> dict_key
{'이름': '7D 건조 망고', type: '당절임'}

하지만 일반적으로 이런 형태로 코드를 사용하는 경우는 거의 없습니다. 따라서 문자열로 사용할 때는 반드시 따옴표를 붙여주세요.


딕셔너리에 값 추가하기/제거하기

딕셔너리에 값을 추가할 때는 키를 기반으로 값을 입력하면 됩니다.

딕셔너리[새로운 키] = 새로운 값

새로운 자료를 추가하고자 한다면 다음과 같이 키를 정하고 값을 입력합니다. 마지막 위치에 "price" 키가 추가되었습니다.

>>> dictionary["price"] = 500
>>> dictionary
{'name': '8D 건조 망고', 'type': '당절임', 'ingredient': ['망고', '설탕', '메타중아황산나트륨', '치자황색소'], 'origin': '필리핀', 'price': 500}

만약 다음과 같이 딕셔너리에 이미 존재하고 있는 키를 지정하고 값을 넣으면 기존의 값을 새로운 값으로 대치하기도 합니다.

>>> dictionary["name"] = "8D 건조 파인애플"
>>> dictionary
{'name': '8D 건조 파인애플', 'type': '당절임', 'ingredient': ['망고', '설탕', '메타중아황산나트륨', '치자황색소'], 'origin': '필리핀', 'price': 500}

딕셔너리 요소의 제거 또한 간단합니다. 리스트 때처럼 del 키워드를 사용하여 특정 키를 지정하면 해당 요소가 제거됩니다.

>>> del dictionary["ingredient"]
>>> dictionary
{'name': '8D 건조 파인애플', 'type': '당절임', 'origin': '필리핀', 'price': 500}

아무것도 없는 딕셔너리에 요소를 추가해 출력하는 예제를 작성해 보겠습니다.

👉 딕셔너리에 요소 추가하기

소스코드 dict02.py

# 딕셔너리를 선언합니다.
dictionary = {}

# 요소 추가 전에 내용을 출력해 봅니다.
print("요소 추가 이전 :", dictionary)

# 딕셔너리에 요소를 추가합니다.
dictionary["name"] = "새로운 이름"
dictionary["head"] = "새로운 정신"
dictionary["body"] = "새로운 몸"

# 출력합니다.
print("요소 추가 이후 :", dictionary)

## 실행 결과
요소 추가 이전 : {}
요소 추가 이후 : {'name': '새로운 이름', 'head': '새로운 정신', 'body': '새로운 몸'}

이번에는 두 개의 요소를 가진 딕셔너리를 선언하고, 이 두 요소를 제거한 후 내용을 출력하는 예제를 작성해 보겠습니다.

👉 딕셔너리에 요소 제거하기

소스코드 dict03.py

# 딕셔너리를 선언합니다.
dictionary = {
    "name" : "7D 건조 망고",
    "type" : "당절임"
}

# 요소 제거 전에 내용을 출력해 봅니다.
print("요소 제거 이전 :", dictionary)

# 딕셔너리의 요소를 제거합니다.
del dictionary["name"]
del dictionary["type"]

# 요소 제거 후에 내용을 출력해 봅니다.
print("요소 제거 이후 :", dictionary)

## 실행 결과
요소 제거 이전 : {'name': '7D 건조 망고', 'type': '당절임'}
요소 제거 이후 : {}

☑️ KeyError 예외

리스트의 길이를 넘는 인덱스에 접근하면 IndexError가 발행했습니다. 딕셔너리도 존재하지 않는 키에 접근하면 마찬가지로 KeyError가 발생합니다.

>>> dictionary = {}
>>> dictionary["Key"]
KeyError                 Traceback (most recent call last)
<ipython-input-25-381564d2dd6a> in <module>
      1 dictionary = {}
----> 2 dictionary["Key"]

KeyError: 'Key'

리스트는 '인덱스'를 기반으로 값을 저장하므로 IndexError, 딕셔너리는 '키'를 기반으로 값을 저장하므로 KeyError가 발생하는 것입니다. 참고로 값을 제거할 때도 마찬가지입니다.

>>> del dectionary["Key"]
KeyError                     Traceback (most recent call last)
<ipython-input-26-e90438d17f1d> in <module>
----> 1 del dictionary["Key"]

KeyError: 'Key'

딕셔너리 내부에 키가 있는지 확인하기

방금 언급했던 것처럼 딕셔너리에 존재하지 않는 키에 접근한다면 KeyError가 발생합니다. 그래서 존재하는 키인지, 존재하지 않는 키인지 확인할 수 있는 방법이 필요합니다.

☑️ in 키워드

리스트 내부에 값이 있는지 없는지 확인할 때 in 키워드를 사용했던 것처럼 딕셔너리 내부에 키가 있는지 없는지 확인할 때도 in 키워드를 사용합니다.

그럼 다음 코드를 살펴보겠습니다. 사용자로부터 접근하고자 하는 키를 입력받은 후, 존재하는 경우에만 접근해서 값을 출력합니다.

👉 키가 존재하는지 확인하고 값에 접근하기

소스코드 key_in.py

# 딕셔너리를 선언합니다.
dictionary = {
    "name" : "홈런볼",
    "type" : "과자",
    "ingredient" : ["밀가루", "설탕", "코코아 분말", "마가린", "난백액"],
    "origin" : "해태"
}

# 사용자로부터 입력을 받습니다.
key = input("> 접근하고자 하는 키 :")

# 출력합니다.
if key in dictionary :
    print(dictionary[key])
else :
    print("존재하지 않는 키에 접근하고 있습니다.")
    
## 실행 결과
> 접근하고자 하는 키 :name
홈런볼
> 접근하고자 하는 키 :price
존재하지 않는 키에 접근하고 있습니다.

☑️ get() 함수

존재하지 않는 키에 접근하는 상황에 대한 두 번째 대처 방법으로는 딕셔너리의 get() 함수를 사용하는 방법이 있습니다. 이전에 문자열이 내부적으로 많은 함수를 갖고 있는 것을 확인했습니다. 딕셔너리도 뒤에 .(마침표)를 찍고 자동 완성 기능으로 확인하면 다양한 기능이 있다는 것을 알 수 있습니다.

이와 관련된 내용은 4-4절에서 자세히 알아보고 여기서는 키의 존재와 관련된 get() 함수만 살펴보겠습니다. get() 함수는 딕셔너리의 키로 값을 추출하는 기능으로 딕셔너리[키]를 입력할 때와 같은 기능을 수행하지만, 존재하지 않는 키에 접근하는 경우 KeyError를 발생시키지 않고 None을 출력합니다.

👉 키가 존재하지 않을 때 None

소스코드 get01.py

# 딕셔너리를 선언합니다.
dictionary = {
    "name" : "홈런볼",
    "type" : "과자",
    "ingredient" : ["밀가루", "설탕", "코코아 분말", "마가린", "난백액"],
    "origin" : "해태"
}

# 존재하지 않는 키에 접근해 봅니다.
value = dictionary.get("존재하지 않는 키")
print("값 :", value)

# None 확인 방법
if value == None :
    print("존재하지 않는 키에 접근했습니다.")
    
## 실행 결과: None
존재하지 않는 키에 접근했습니다.

_________________________

## get 함수 딕셔너리[키]와 같은지 확인하기
a = dictionary.get("ingredient")
print("값 :", a)

## 실행 결과: ['밀가루', '설탕', '코코아 분말', '마가린', '난백액']

for 반복문 : 딕셔너리와 함께 사용하기

이번에는 for 반복문과 딕셔너리를 조합하는 방법을 살펴보겠습니다. for 반복문과 딕셔너리를 조합해서 사용하면 다음과 같은 형태가 됩니다. 여기서 주의할 점은 딕셔너리 내부에 있는 키가 변수에 들어간다는 것입니다.

for 키 변수 in 딕셔너리 :
    코드

딕셔너리 자체는 어렵지 않게 사용할 수 있습니다. 중요한 것은 활용입니다. 손코딩 결과를 통해 살펴보겠습니다.

👉 for 반복문과 딕셔너리

소스코드 for_dict.py

# 딕셔너리를 선언합니다.
dictionary = {
    "name" : "홈런볼",
    "type" : "과자",
    "ingredient" : ["밀가루", "설탕", "코코아 분말", "마가린", "난백액"],
    "origin" : "해태"
}

# for 반복문을 사용합니다.
for key in dictionary :
    # 출력합니다.
    print(key, ":", dictionary[key])
    
## 실행 결과
name : 홈런볼
type : 과자
ingredient : ['밀가루', '설탕', '코코아 분말', '마가린', '난백액']
origin : 해태

만약 딕셔너리 내부에 존재하지 않는 키라면 Error가 뜨게 됩니다. 그래서 딕셔너리 내부에 키가 있는지를 확인하기 위해 in 이라는 변수를 사용하게 됩니다.

dictionary = {
    "종족" : "강아지",
    "이름" : "호랭"
}
if "나이" in dictionary :
    print(dictionary["나이"])
else :
    print("없는 키입니다!")
없는 키입니다!
ᅠ
ᅠ
# get 함수 사용하기 없으면 None 출력
print(dictionary.get("나이"))
Nome
ᅠ
ᅠ
# dictionary.get() 함수 사용하기
dictionary = {
    "종족" : "강아지",
    "이름" : "호랭"
}
if dictionary.get("나이") == "None" :
    print(dictionary.get("나이"))
else :
    print("없는 키 입니다!")

마무리

🔍 3가지 키워드 핵심 포인트

  • 딕셔너리는 키를 기반으로 여러 자료를 저장하는 자료형입니다.
  • 는 딕셔너리 내부에서 값에 접근할 때 사용하는 것입니다.
  • 은 딕셔너리 내부에 있는 각각의 내용을 의미합니다.

🔍 확인문제

1. 다음 표에서 dict_a의 결과가 나오도록 빈칸을 채워보세요.

dict_a의 값dict_a에 적용할 코드dict_a의 결과
{}dict_a["name"] = "구름"{'name' : '구름'}
{"name" : "구름}del dict_a["name]{}

2. 딕셔너리와 리스트를 조합하면 다음 코드의 변수 pets 처럼 다양한 정보를 축적할 수 있습니다. 이를 실행결과처럼 출력되도록 빈칸에 반복문과 print() 함수를 조합해 보세요.

# 딕셔너리의 리스트를 선언합니다.
pets = [
    {"name" : "구름", "age" : 5},
    {"name" : "초코", "age" : 3},
    {"name" : "절미", "age" : 1},
    {"name" : "호랭", "age" : 1}
]

print("# 우리 동네 애완 동물들")
for pet in pets :
#1 pets 안에 있는 딕셔너리 하나하나가 pet 변수 안에 들어가며, 차례차례 반복하게 된다
    print("{} {}살".format(pet["name"], pet["age"]))
    
## 실행 결과
# 우리 동네 애완 동물들
구름 5살
초코 3살
절미 1살
호랭 1

3. 다음 비칸을 채워서 numbers 내부에 들어 있는 숫자가 몇 번 등장하는지를 출력하는 코드를 작성해 보세요.

# 숫자는 무작위로 입력해도 상관 없습니다.
#1
numbers = [1, 2, 3, 4, 1, 2, 3, 1, 2, 1]
counter = {}

for number in numbers :
#2 number = 1
#5 number = 2
#8 number = 3
#11 number = 4
#14 number = 1
#17 number = 2
#20 number = 3
#23 number = 1
#26 number = 2
#29 number = 1
    if number in counter :
    # if 키 in 딕셔너리 / if 요소 in 리스트
    #3 만약 1이 {}에 있으면
    #6 만약 2가 {1:1}에 있으면
    #9 만약 3이 {1:1, 2:1}에 있으면
    #12 만약 4가 {1:1, 2:1, 3:1}에 있으면
    #15 만약 1이 {1:1, 2:1, 3:1, 4:1}에 있으면
    #18 만약 2가 {1:2, 2:1, 3:1, 4:1}에 있으면
    #21 만약 3이 {1:2, 2:2, 3:1, 4:1}에 있으면
    #24 만약 1이 {1:2, 2:2, 3:2, 4:1}에 있으면
    #27 만약 2가 {1:3, 2:2, 3:2, 4:1}에 있으면
    #30 만약 1이 {1:3, 2:3, 3:2, 4:1}에 있으면
        counter[number] += 1
        # 딕셔너리[키이름] = 그 키의 값
        #16 값에 +1한 값을 넣어라 {1:2, 2:1, 3:1, 4:1}
        #19 값에 +1한 값을 넣어라 {1:2, 2:2, 3:1, 4:1}
        #22 값에 +1한 값을 넣어라 {1:2, 2:2, 3:2, 4:1}
        #25 값에 +1한 값을 넣어라 {1:3, 2:2, 3:2, 4:1}
        #28 값에 +1한 값을 넣어라 {1:3, 2:3, 3:2, 4:1}
        #31 값에 +1한 값을 넣어라 {1:4, 2:3, 3:2, 4:1}
    else :
        counter[number] = 1
        #4 없으면 counter[number] = 1이 된다. 즉 {1:1}
        #7 없으면 {1:1, 2:1}
        #10 없으면 {1:1, 2:1, 3:1}
        #13 없으면 {1:1, 2:1, 3:1, 4:1}
print(counter)
#32 {1:4, 2:3, 3:2, 4:1}
{1: 4, 2: 3, 3: 2, 4: 1}

# 1번
number

4. 파이썬은 다음과 같은 방법으로 특정 값이 어떤 자료형인지 확인할 수 있습니다.

type("문자열") is str  # 문자열인지 확인
type([]) is list  # 리스트인지 확인
type({}) is dict  # 딕셔너리인지 확인

이를 활용해 다음 빈칸을 채워 실행결과와 같이 출력되게 만들어 보세요.

# 딕셔너리를 선언합니다.
#1 character에 아래와 같은 값을 넣습니다
character = {
    "name" : "기사", 
    "level" : 12,
    "items" : {
        "sword" : "불꽃의 검",
        "armor" : "풀플레이트"
        },
    "skill" : ["베기", "세게 베기", "아주 세게 베기"]
    }

#for 반복문을 사용합니다.
for key in character :
    if type(character[key]) is dict :
    #6 만약 items 값의 타입이 딕셔너리라면
        for k in character[key] :
        #7 "sword" : "불꽃의 검", "armor" : "풀플레이트" 를 k라는 변수로 반복 실행한다
        #  여기서 k는 키 이며 ("sword", "armor") 그에 해당하는 값은 character[key][k] ("불꽃의 검", "폴플레이트"이다
            print("{} : {}".format(k, character[key][k]))
            #8 'sword : 불꽃의 검' 을 출력해라
            #9 'armor : 풀플레이트' 를 출력해라
    elif type(character[key]) is list : 
    #10 만약 skill 값의 타입이 list 라면
        for item in character[key] :
        #11 베기, 세게 베기, 아주 세게 베기 값을 item이라는 변수로 반복 실행한다.
            print("{} : {}".format(key, item))
            #12 'skill : 베기' 를 출력한다.
            #13 'skill : 세게 베기' 를 출력한다.
            #14 'skill : 아주 세게 베기' 를 출력한다.
    else : 
    #2 만약 name 값의 타입이 딕셔너리도 리스트도 아니라면
    #4 만약 level 값의 타입이 딕셔너리도 리스트도 아니라면
        print("{} : {}".format(key,character[key]))
        #3 'name : 기사' 를 출력해라
        #5 'level : 12' 를 출력해라

## 실행 결과
name : 기사
level : 12
sword : 불꽃의 검
armor : 풀플레이트
skill : 베기
skill : 세게 베기
skill : 아주 세게 베기

윤성인, 『혼자 공부하는 파이썬』, 한빛미디어(2019), p160-173.

profile
라쏘, 릿지, 엘라스틱넷 중 라쏘를 담당하고 있습니다.

0개의 댓글