{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 6. 인덱스를 사용하는 대신 대입을 사용해 데이터를 언패킹하라" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬에는 값으로 이뤄진 불변(immutable) 순서쌍을 만들어낼 수 있는 tuple 내장타입이 있다.\n", "\n", "가장 짧은 튜플은 딕셔너리의 키-값 쌍과 비슷하게 두 값으로 이뤄진다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "snack_calories = {\n", " '감자칩': 140,\n", " '팝콘': 80,\n", " '땅콩': 190,\n", "}" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'감자칩': 140, '팝콘': 80, '땅콩': 190}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snack_calories" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(('감자칩', 140), ('팝콘', 80), ('땅콩', 190))\n" ] } ], "source": [ "items = tuple(snack_calories.items())\n", "print(items)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "item = ('호박엿', '식혜')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "호박엿 & 식혜\n" ] } ], "source": [ "first = item[0]\n", "second = item[1]\n", "print(first, '&', second)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "튜플은 인덱스를 통해 변경 불가능 (immutable)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m<ipython-input-6-a813456798f0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mpair\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'약과'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'호박엿'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mpair\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'타래과'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "source": [ "pair = ('약과', '호박엿')\n", "pair[0] = '타래과'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬에는 **언패킹** 구문이 있다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "호박엿 & 식혜\n" ] } ], "source": [ "item = ('호박엿', '식혜')\n", "first, second = item # 언퍀킹\n", "print(first, '&', second)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "인덱스 사용보다 시각적인 잡음이 적고, 이터러블이 들어간 경우 등 다양한 패턴을 언패킹 구문에 사용할 수 있다.\n", "\n", "다음과 같은 코드는 추천하지는 않지만 가능하다는 사실을 알고 있는 것도 중요하다." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "favorite_snacks = {\n", " '짭조름한 과자': ('프레즐', 100),\n", " '달콤한 과자': ('쿠키', 180),\n", " '채소': ('당근', 20),\n", "}\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "((type1, (name1, cals1)),\n", " (type2, (name2, cals2)),\n", " (type3, (name3, cals3))) = favorite_snacks.items()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "제일 좋아하는 짭조름한 과자 는 프레즐, 100 칼로리입니다.\n", "제일 좋아하는 달콤한 과자 는 쿠키, 180 칼로리입니다.\n", "제일 좋아하는 채소 는 당근, 20 칼로리입니다.\n" ] } ], "source": [ "print(f'제일 좋아하는 {type1} 는 {name1}, {cals1} 칼로리입니다.')\n", "print(f'제일 좋아하는 {type2} 는 {name2}, {cals2} 칼로리입니다.')\n", "print(f'제일 좋아하는 {type3} 는 {name3}, {cals3} 칼로리입니다.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "언패킹을 사용하면 임시 변수를 정의하지 않고도 값을 맞바꿀 수 있다.\n", "\n", "다음은 오름차군 정렬 알고리즘이다." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def bubble_sort(a):\n", " for _ in range(len(a)):\n", " for i in range(1, len(a)):\n", " if a[i] < a[i-1]:\n", " temp = a[i]\n", " a[i] = a[i-1]\n", " a[i-1] = temp" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "names = ['프레즐', '당근', '쑥갓', '베이컨']" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "bubble_sort(names)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['당근', '베이컨', '쑥갓', '프레즐']\n" ] } ], "source": [ "print(names)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "언패킹 사용" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "def bubble_sort(a):\n", " for _ in range(len(a)):\n", " for i in range(1, len(a)):\n", " if a[i] < a[i-1]:\n", " a[i-1], a[i] = a[i], a[i-1]" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['당근', '베이컨', '쑥갓', '프레즐']\n" ] } ], "source": [ "names = ['프레즐', '당근', '쑥갓', '베이컨']\n", "bubble_sort(names)\n", "print(names)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "우항 값이 임시 tuple에 들어가고 좌항에 임시 tuple의 값을 대입한다.\n", "\n", "그 후 임시 tuple은 사라진다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "언패킹의 용례 중에서 또 한 가지 쓸모 있는 것으로 for 루프 또는 그와 비슷한 다른 요소(컴프리헨션이나 제너레이터 식)의 대상인 리스트의 원소를 언패킹하는 것이 있다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. 언패킹 X" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#1: 베이컨 은 350 칼로리 입니다.\n", "#2: 도넛 은 240 칼로리 입니다.\n", "#3: 머핀 은 190 칼로리 입니다.\n" ] } ], "source": [ "snacks = [('베이컨', 350), ('도넛', 240), ('머핀', 190)]\n", "for i in range(len(snacks)):\n", " item = snacks[i]\n", " name = item[0]\n", " calories = item[1]\n", " print(f'#{i+1}: {name} 은 {calories} 칼로리 입니다.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. 언패킹 O" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#1: 베이컨 은 350 칼로리입니다.\n", "#2: 도넛 은 240 칼로리입니다.\n", "#3: 머핀 은 190 칼로리입니다.\n" ] } ], "source": [ "for rank, (name, calories) in enumerate(snacks, 1):\n", " print(f'#{rank}: {name} 은 {calories} 칼로리입니다.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pythonic한 방식이다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 기억해야 할 내용\n", "- 파이썬은 한 문장 안에서 여러 값을 대입할 수 있는 언패킹이라는 특별한 문법을 제공한다.\n", "- 파이썬 언패킹은 일반화돼 있으므로 모든 이터러블에 적용할 수 있다. 그리고 이터러블이 여러 계층으로 내포된 경우에도 언패킹을 적용할 수 있다.\n", "- 인덱스를 사용해 시퀀스 내부에 접근하는 대신 언패킹을 사용해 시각적인 잡음을 줄이고 코드를 더 명확하게 만들라." ] } ], "metadata": { "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.8.2" } }, "nbformat": 4, "nbformat_minor": 4 }