{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "***\n", "# 12. 사전(Dictionaries)\n", "***\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 1 사전 활용법\n", "***\n", "- 사전(Dictionary) 객체의 특징\n", " - 집합적 자료형\n", " - 자료의 순서를 정하지 않는 매핑(Mapping)형\n", " - 키(Key)를 이용하여 값(Value)에 접근\n", " - 시퀀스 자료형은 아님\n", " - 키와 값의 매핑 1개를 아이템(item)이라고 부름" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9\n" ] } ], "source": [ "member = {'basketball': 5, 'soccer': 11, 'baseball': 9}\n", "print(member['baseball']) # 검색" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 값을 저장할 시에 키를 사용\n", " - 키가 없다면 새로운 키와 값의 아이템이 생성\n", " - 키가 이미 존재한다면 그 키에 해당하는 값이 변경" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'basketball': 5, 'soccer': 11, 'baseball': 9, 'volleyball': 6}\n", "4\n" ] } ], "source": [ "member = {'basketball': 5, 'soccer': 11, 'baseball': 9}\n", "member['volleyball'] = 7 # 새로운 아이템 설정\n", "member['volleyball'] = 6 # 변경\n", "print(member)\n", "print(len(member)) # 아이템의 개수 반환 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전을 출력하면 각 아이템들이 임의의 순서로 출력된다.\n", " - 마치 순서대로 출력이 되는 것 처럼 보이지만, 사전내에 있는 아이템들은 순서정보가 없음.\n", " \n", "- 내부적으로 키 내용에 대해 해쉬(Hash) 기법을 사용\n", " - 검색 속도가 매우 빠름\n", " - [참고]: http://www.laurentluce.com/posts/python-dictionary-implementation/\n", "- 키와 값 매핑에 대한 아이템을 삭제할 때에는 del과 함께 키값 명시 " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'soccer': 11, 'baseball': 9}\n" ] } ], "source": [ "member = {'basketball':5, 'soccer':11, 'baseball':9}\n", "del member['basketball'] # 항목 삭제\n", "print(member)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- [중요] 키는 변경 불가능 (Immutable) 자료만 가능\n", " - 문자열, 숫자, 튜플은 가능\n", " - 리스트, 사전은 키가 될 수 없음\n", "- 반면에 사전에 입력되는 값은 임의의 객체" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'str': 'abc', 1: 4, (1, 2, 3): 'tuple'}\n" ] } ], "source": [ "d = {}\n", "d['str'] = 'abc'\n", "d[1] = 4\n", "d[(1,2,3)] = 'tuple'\n", "print(d)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unhashable type: 'list'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0md\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'list'\u001b[0m \u001b[0;31m# 리스트는 키가 될 수 없다.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'" ] } ], "source": [ "d[[1,2,3]] = 'list' # 리스트는 키가 될 수 없다." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unhashable type: 'dict'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0md\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3\u001b[0m \u001b[0;31m# 사전은 키가 될 수 없다.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'dict'" ] } ], "source": [ "d[{1:2}] = 3 # 사전은 키가 될 수 없다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 함수 이름(함수 객체)은 사전의 키나 값으로 사용 가능함" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9\n", "-1\n" ] } ], "source": [ "def add(a, b):\n", " return a + b\n", "\n", "def sub(a, b):\n", " return a - b\n", "\n", "action = {0: add, 1: sub} # 함수 이름을 사전의 값으로 사용\n", "print(action[0](4, 5))\n", "print(action[1](4, 5))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "action2 = {add: 1, sub: 2} # 함수 이름을 사전의 키로 사용\n", "print(action2[add])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전을 생성하는 다른 방법: 내장함수 dict() 사용" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "{'one': 1, 'two': 2}\n", "{'one': 1, 'two': 2}\n", "{'one': 1, 'two': 2}\n" ] } ], "source": [ "d = dict()\n", "print(type(d))\n", "print()\n", "\n", "print(dict(one=1, two=2))\n", "print(dict([('one', 1), ('two', 2)]))\n", "print(dict({'one':1, 'two':2}))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- [중요] zip(A, B): 두 개의 컨테이너/시퀀스 자료 A, B에 속한 원소들을 순서대로 쌍으로 묶은 튜플들을 반환할 수 있는 zip 객체 반환" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- zip 객체를 사전으로 변환하기" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "{'one': 1, 'two': 2, 'three': 3}\n" ] } ], "source": [ "keys = ['one', 'two', 'three']\n", "values = (1, 2, 3)\n", "print(zip(keys, values)) \n", "print(dict(zip(keys, values)))" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'one': 1, 'two': 2, 'three': 3}\n" ] } ], "source": [ "keys = ['one', 'two', 'three', 'four']\n", "values = (1, 2, 3)\n", "print(dict(zip(keys, values)))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'one': 1, 'two': 2, 'three': 3}\n" ] } ], "source": [ "keys = ['one', 'two', 'three']\n", "values = (1, 2, 3, 4)\n", "print(dict(zip(keys, values)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- zip 객체를 리스트로 변환하기" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('one', 1), ('two', 2), ('three', 3)]\n" ] } ], "source": [ "keys = ['one', 'two', 'three']\n", "values = (1, 2, 3)\n", "print(list(zip(keys, values)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 2 사전 메소드\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전이 지원하는 중요 메소드\n", " - D.keys(): 사전 D에서 키를 차례로 반환할 수 있는 dict_keys 객체 반환\n", " - D.values(): 사전 D에서 값을 차례로 반환할 수 있는 dict_values 객체 반환\n", " - D.items(): 사전 D에서 각 (키, 값) 아이템을 차례로 반환할 수 있는 dict_items 객체 반환\n", "- key in D: 사전 D안에 key를 키값을 가진 아이템이 있는지 확인" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dict_keys(['jack', 'jin', 'Joseph'])\n", "dict_values([9465215, 1111, 6584321])\n", "dict_items([('jack', 9465215), ('jin', 1111), ('Joseph', 6584321)])\n", "\n", "True\n", "False\n" ] } ], "source": [ "phone = {'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "\n", "print(phone.keys()) \n", "print(phone.values()) \n", "print(phone.items())\n", "print()\n", "print('jack' in phone) # 'jack'이 phone의 키에 포함되어 있는가?\n", "print('lee' in phone)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- D2 = D.copy(): 사전 D를 복사하여 D2 사전에 할당한다." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'jack': 1234, 'jin': 1111, 'Joseph': 6584321}\n", "{'jack': 1234, 'jin': 1111, 'Joseph': 6584321}\n", "\n", "{'jack': 1111, 'jin': 1111, 'Joseph': 6584321}\n", "{'jack': 1234, 'jin': 1111, 'Joseph': 6584321}\n" ] } ], "source": [ "phone = {'jack':9465215, 'jin':1111, 'Joseph':6584321}\n", "p = phone # 사전 레퍼런스 복사. 사전 객체는 공유된다.\n", "\n", "phone['jack'] = 1234 # phone을 변경하면\n", "print(phone)\n", "print(p) # p도 함께 변경된다.\n", "print()\n", "\n", "ph = phone.copy() # 사전복사. 별도의 사전 객체가 마련된다.\n", "phone['jack'] = 1111 # phone을 바꿔도\n", "print(phone)\n", "print(ph) # ph는 바뀌지 않는다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- [주의] D.copy()는 Shallow Copy를 수행한다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'a': [1, 2, 3], 'b': 4}\n", "{'a': [1, 2, 3], 'b': 4}\n", "\n", "{'a': [1, 2, 3], 'b': 100}\n", "{'a': [1, 2, 3], 'b': 4}\n", "\n", "{'a': [100, 2, 3], 'b': 100}\n", "{'a': [100, 2, 3], 'b': 4}\n" ] } ], "source": [ "phone = {'a': [1,2,3], 'b': 4}\n", "phone2 = phone.copy()\n", "print(phone)\n", "print(phone2)\n", "print()\n", "\n", "phone['b'] = 100\n", "print(phone)\n", "print(phone2)\n", "print()\n", "\n", "phone['a'][0] = 100\n", "print(phone)\n", "print(phone2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![image](../images/shallow_copy.png)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9465215\n", "None\n" ] } ], "source": [ "ph = {'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "\n", "print(ph.get('jack')) # 'jack'에 대한 값을 얻는다. ph['jack']과 같다.\n", "print(ph.get('gslee')) # 'gslee'에 대한 값을 얻는다. 값이 없는 경우 None반환" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "ename": "KeyError", "evalue": "'gslee'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mph\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'jack'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m9465215\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'jin'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1111\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Joseph'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m6584321\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mph\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'gslee'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# ph['gslee']는 키가 없는 경우 예외발생\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mKeyError\u001b[0m: 'gslee'" ] } ], "source": [ "ph = {'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "print(ph['gslee']) # ph['gslee']는 키가 없는 경우 예외발생" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5284\n", "{'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "\n", "('Joseph', 6584321)\n", "{'jack': 9465215, 'jin': 1111}\n", "\n", "('jin', 1111)\n", "{'jack': 9465215}\n", "\n", "9465215\n", "{}\n" ] } ], "source": [ "ph = {'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "print(ph.get('gslee', 5284)) # 인수를 하나 더 제공하면 'gslee'가 없는 경우에 5284 리턴\n", "print(ph) # 사전에는 변화가 없다\n", "print()\n", "\n", "print(ph.popitem()) # 임의의 아이템을 꺼낸다.\n", "print(ph)\n", "print()\n", "\n", "print(ph.popitem()) # 임의의 아이템을 꺼낸다.\n", "print(ph)\n", "print()\n", "\n", "print(ph.pop('jack')) # 키 값을 통해 해당 아이템을 지정하여 꺼낸다.\n", "print(ph)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'jack': 9465215, 'jin': 1111, 'Joseph': 6584321, 'kim': 12312, 'lee': 9090}\n", "\n", "{}\n" ] } ], "source": [ "phone = {'jack': 9465215, 'jin': 1111, 'Joseph': 6584321}\n", "ph = {'kim': 12312, 'lee': 9090}\n", "\n", "phone.update(ph) # 사전 phone의 내용을 ph으로 추가 갱신\n", "print(phone)\n", "print()\n", "phone.clear() # 사전의 모든 입력을 없앤다.\n", "print(phone)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 3 루프를 이용한 사전 내용 참조\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전의 모든 키값을 순차적으로 참조하는 방법" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1\n", "b 2\n", "c 3\n" ] } ], "source": [ "D = {'a':1, 'b':2, 'c':3}\n", "for key in D.keys():\n", " print(key, D[key])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전 자체를 for루프에 활용하면 키에 대한 루프가 실행된다." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1\n", "b 2\n", "c 3\n" ] } ], "source": [ "D = {'a':1, 'b':2, 'c':3}\n", "for key in D:\n", " print(key, D[key])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 키와 값을 동시에 참조하려면 D.items()를 활용한다." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1\n", "b 2\n", "c 3\n" ] } ], "source": [ "for key, value in D.items():\n", " print(key, value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 사전에 입력된 아이템들은 일정한 순서가 없다.\n", "- 키값에 대한 정렬은 아이템들을 리스트로 뽑은 다음에 해당 리스트에 있는 sort() 함수를 활용한다." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('c', 1), ('a', 2), ('b', 3)]\n", "\n", "[('a', 2), ('b', 3), ('c', 1)]\n", "\n", "a 2\n", "b 3\n", "c 1\n" ] } ], "source": [ "D = {'c':1, 'a':2, 'b':3}\n", "#items = D.items()\n", "items = list(D.items())\n", "print(items)\n", "print()\n", "\n", "items.sort()\n", "print(items)\n", "print()\n", "\n", "for k, v in items:\n", " print(k, v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 위 리스트에서 각 튜플 원소의 두번째 값을 기준으로 정렬을 해보시오 (각자 실습)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

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

" ] } ], "metadata": { "celltoolbar": "Raw Cell Format", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 1 }