ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 5. (2) 파이썬 자료형 딕셔너리
    파이썬(Python) 강의 2019. 2. 9. 16:52

    이 포스트를 통해 파이썬 자료형 딕셔너리(Python Datatype Dictionary)를 알아보도록 한다. 지난시간에 딕셔너리 자료형의 초기화, 삽입, 수정, 삭제에 이어 오늘은 파이썬이 제공하는 딕셔너리 함수들을 이용해 다양한 실습을 해 볼 예정이다.

    들어가기전에

    이 포스트는 여러분이 파이썬을 설치했고 각자 원하는 IDE를 이용해 파이썬을 개발한다고 가정한다. 대화형(Interactive) 터미널을 사용해도 상관 없다. 혹시 파이썬을 설치하지 않았다면  1.파이썬 설치 및 개발환경 설정 이 포스트에서 파이썬과 파이썬 개발환경을 먼저 셋업하길 바란다. 앞서 말했듯이 반드시 실습 해 보길 바라고 30분 이상 소요하지 말라. 

    예상 소요 시간 30분 이내

    목표

    • len
    • key membership
    • keys
    • values
    • items
    • copy
    • get(key, default)
    • update

    len

    일단 가장 기본적인 함수인 len함수부터 시작 해 보도록 하자.

    # dictionary length

    dic = {
    'name' : 'fsoftwareengineer',
    'age' : 17
    }
    print(len(dic))

    2

    결과로 key-value 쌍의 갯수가 나오는 것을 알 수 있다. len함수는 리스트에서도 했으니 이만 넘어가도록 하겠다.

    key membership

    여러분은 어떤 key가 딕셔너리에 존재하는지 알아보고 싶다. 그렇때 어떻게 하겠는가? 딕셔너리를 반복문으로 돌면서 해당 key를 검색하겠는가? 다른 언어라면 그래야 했을 지도 모르지만 파이썬에서는 그러지 않아도 된다. 파이썬에서는 'in'이라는 키워드를 통해 어떤 key가 딕셔너리 내부에 존재하는지 안 하는지를 찾을 수 있다.

    # does key exist in dictionary? dic = {
    'name' : 'fsoftwareengineer',
    'age' : 17
    }
    print('name' in dic) # key in dictionary True

    'name'이라는 key가 dic이라는 딕셔너리에 in 들어있는가? 하고 물어보는 것이다. age로도 해 보도록 하자.

    # does key exist in dictionary? dic = {
    'name' : 'fsoftwareengineer',
    'age' : 17
    }
    print('age' in dic) True

    True - 참이라는 결과 값이 나오는 것을 확인 할 수 있다. (Boolean 자료형에 대해서는 다음 포스트에서 설명하도록 하겠다.)

    그렇다면 존재하지 않는 key를 집어넣으면 어떻게 될까?

    # does key exist in dictionary?
    dic = {
    'name' : 'fsoftwareengineer',
    'age' : 17
    }
    print('height' in dic) False

    'height'은  dic이라는 딕셔너리에 존재하지 않으므로 False가 리턴 되는 것을 확인 할 수 있다.

    keys

    가끔 이 딕셔너리에 어떤 key들이 존재하는지 확인 하고 싶을 때가 있는데 그럴 때는 keys라는 함수를 사용하면 된다.

    # get all the keys from dictionary dic = {
    'name' : 'fsoftwareengineer',
    'age' : 17
    }
    print(dic.keys()) dict_keys(['name', 'age'])

    결과 화면 dict_keys(dictionary's keys라는 뜻)가 출력 된 것을 확인 할 수 있다. 그렇다면 이 key들을 리스트의 형태로 받아 올 수는 없을까?

    # get all the keys from dictionary and create a list of them dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    keyList = list(dic.keys());
    print(keyList) ['name', 'age']

    그것은 바로 list라는 함수를 통해 가능하다! 조금 복잡하다면 나눠서 살펴보자.

    # get all the keys from dictionary and create a list of them dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    dicKeys = dic.keys();
    print("Dictionary Keys : ", dicKeys)
    keyList = list(dicKeys);
    print("Key List : ", keyList) Dictionary Keys : dict_keys(['name', 'age']) Key List : ['name', 'age']

    dicKeys에 dic_keys라는 오브젝트가 들어있는데, 이는 딕셔너리의 view 오브젝트이다. 간단히 말에 보여주기 위해  파이썬 딕셔너리가 자체적으로 사용하는 오브젝트라고 보면 된다. 리스트로 이를 바꾸기 위해서  keyList에 list함수를 이용해 초기화 하면 두 번째 프린트 문에서 리스트의 형태로 바뀐 것을 확인 할 수 있다.

    values

    key가 아닌 딕셔너리 내부의 value들만 가져오고 싶다면 value함수를 사용 할 수 있다.

    # get all the values from dictionary dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    print(dic.values()) dict_values(['fsoftwareengineer', 17])

    values도 마찬가지로 view오브젝트로 리턴 되는 것을 확인 할 수 있다. dic_values 오브젝트를 리스트로 바꿔 프린트 해보자.

    # get all the values from dictionary and create a list of them dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    dicValues = list(dic.values())
    print(dicValues) ['fsoftwareengineer', 17]

    위처럼 리스트로 출력 되는 것을 확인 할 수 있다.

    items

    위에서 key를 가져오는 방법과 value를 가져오는 방법을 확인 해 보았다. 그러면 (key, value) 쌍을 통째로 가져오는 건 어떻게 할까? 바로 items함수를 이용해서 한다.

    # get all (key, value) pairs dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    print(dic.items()) dict_items([('name', 'fsoftwareengineer'), ('age', 17)])

    그렇다면 얘네들은 key-value가 한 쌍인데 리스트로 가져 올 수 있을까? 한번 해보자.

    # get all (key, value) pairs and create a list of them dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    dicItems = dic.items();
    dicList
    = list(dicItems)
    print(dicList) [('name', 'fsoftwareengineer'), ('age', 17)]

    리스트로 생성 된 것을 확인 할 수 있다. 어? 잠깐. 그런데 그 안의 () 괄호는 무엇인가? ( ) <- 이 괄호는 튜플(Tuple)이라고 부르는 자료형인데 리스트와 매우 비슷하지만 한번 생성 된 후에는 값을 변경 할 수 없다는 특성이 있다. key-value 쌍은 관계가 정해져 있기 때문에 마음대로 변경하지 못하게 하기 위해 튜플로 만들어 졌다, 라고 생각하면 이해하기 쉬울 것 같다.

    copy

    한 딕셔너리를 복사하여 새 딕셔너리를 만들고 싶을 때 copy함수를 사용 할 수 있다.

    # copy dictionary
    dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    newDic = dic.copy();
    print(newDic) {'name': 'fsoftwareengineer', 'age': 17}

    그렇다면 copy의 진정한 의미는 무엇인가? newDic = dic과 뭐가 다른가? 여러분 리스트에서 '레퍼런스'에 대해 이야기 했던 것을 기억하는가? 아래를 보자.

    # just assign dic to newDic, why bother using copy? dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    newDic = dic
    newDic
    ['name'] = "something else"
    print(dic)
    print(newDic) {'name': 'something else', 'age': 17} {'name': 'something else', 'age': 17}

    이럴수가, 나는 분명히 newDic에 dic의 값인 { 'name': 'fsoftwareengineer', 'age':17 }을 집어 넣고 newDic을 수정했는데 dic까지 수정이 되어버렸다. 이게 대체 무슨일인가?!

    레퍼런스에 대한 이야기를 했을 때, 웹사이트를 예로 들었었다. 그 예를 다시 들어보자. 내가 웹사이트의 주소를 doc이라고 불리는 파일에 저장 해 놓았다고 하자. 나는 그 웹사이트의 내용이 보고 싶을 때 마다, doc파일에서 웹사이트 주소를 복사해서 브라우저에 붙여넣기 해 들어간다. 그런데 내가 이번에는 newDoc이라는 파일을 새로 만들었고, 그 안에 doc의 내용물을 복사/붙여넣기 했다고 하자. 그렇다면  newDoc에는 무슨 값이 들어있는가? doc이 갖고 있는 웹사이트 주소가 들어있다! 만약 웹사이트의 내용이 변경되면 doc에 있는 주소를 따라 들어가던 newDoc에 있는 주소를 따라 들어가던 같은 변경된결과물을 보게 될 것이다. 반면 copy는 이렇다. 

    주의! 헷갈리지 말자. dic자체에 { 'name' ... } 딕셔너리가 저장되어 있는게 아니라, 이 딕셔너리의 레퍼런스가 저장되어 있다. 가끔 copy/call by value 인지 copy/call by reference를 헷갈려 하는 사람들이 있는데(모르는 독자들은 그냥 넘어가도 된다) dic의 값 자체가 레퍼런스가 들어있으므로 이는 copy by value이다. value자체가 레퍼런스인 것일 뿐이다.

    dic.copy()를 한다는 것은 웹사이트의 예를들었을 때, 그 웹사이트의 내용물을 전부 복사 붙여넣기 해서 새로운 주소를 가진 새 웹사이트를 만드는 것이다. 그러면 그 둘은 내용물만 같이 서로 연관이 없는 웹사이트이기 때문에 한쪽이 뭔가를 변경해도 다른쪽에 아무런 영향도 주지 않는다. 마찬가지로 딕셔너리 카피도 함수를 부르는 순간 파이썬이 새로운 딕셔너리를 만든 후 값을 전부 복사 해 넣는다. 그러므로 두 딕셔너리는 내용물만 같을 뿐 실제로 같은 딕셔너리는 아니게 된다.

    # use copy to create a new dictionary dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    newDic = dic.copy()
    newDic['name'] = "something else"
    print(dic)
    print(newDic)

    {'name': 'fsoftwareengineer', 'age': 17} {'name': 'something else', 'age': 17}

    이를 증명하듯 copy로 생성된 newDic만 이름이 변경되고 dic의 이름은 그대로 인 것을 확인 할 수 있다.

    get(key, default)

    어떤 value를 key를 이용해 가져올 때, 만약 그 키(key)가 없으면 디폴트 값을 넣고 싶을 때가 있다. 그럴 때 get(key, default)를 사용한다. key가 존재하지 않으면 default 값을 리턴한다.

    # use get to get default if key doesn't exist dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    value = dic.get('height', 188)
    print(value)

    188

    key-value를 추가하고 다시 실행 해 보자,

    # confirm when the key exists, it returns the value of that key dic = {
    'name': 'fsoftwareengineer',
    'age': 17,
    'height' : 150
    }
    value = dic.get('height', 188)
    print(value)

    150

    key가 존재하면 그 key의 값을 반환하는 것을 알 수 있다.

    update

    어떤 두 딕셔너리를 합치고 싶다면(merge) 어떻게 하겠는가? update 함수를 통해 가능하다.

    # merge two dicionaries dic = {
    'name': 'fsoftwareengineer',
    'age': 17
    }
    newDic = {
    'height': 150,
    'grade': 'A'
    }
    dic.update(newDic)
    print(dic) {'name': 'fsoftwareengineer', 'age': 17, 'height': 150, 'grade': 'A'}

    두 딕셔너리가 하나로 합쳐진 것을 확인 할 수 있다.

    연습문제: newDic은 어떻게 되었는가? newDic을 출력 해 보고 newDic이 변경되었는지 아닌지 확인 해 보아라. 그러면 '레퍼런스'의 관점에서 볼 때 newDic은 값이 복사되었는가 레퍼런스가 복사되었는가?

     이번 포스트를 통해서 파이썬3의 딕셔너리가 제공하는 각종 함수들과 이 함수들을 이용하는 방법에 대해서 알아보았다. 이번 포스트에서는 함수 사용법 외에도 레퍼런스에 대한 설명이 있으므로 레퍼런스에 대해 더 이해 하게 되는 기회가 될 수 있을 것 같다. 다음 시간에는 파이썬 자료형을 잠깐 쉬고 파이썬의 구문으로 살짝 뛰어넘을 예정이다. 구체적으로 Boolean자료형, if-else구문과 for, while에 대해서 설명 할 예정이다. 갑자기 자료형을 쉬고 문법 구문에 대해 설명 하는 이유는 이후의 자료형들 부터 if-else와 while그리고 boolean을 알고 있으면 더 쉽게 이해되기 때문이다. 또한 계속 자료형만 주구장창 하는 것도 지겨우므로 이제 로직(Logic)의 세계를 조금 들여다 보는 것도 나쁘지 않을 것 같다는 생각이다.

    댓글

f.software engineer @ All Right Reserved