{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 23. 키워드 인자로 선택적인 기능을 제공하라" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "함수를 호출할때 위치에 따라 인자를 넘길 수 있다" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def remainder(number, divisor):\n", " return number % divisor" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "assert remainder(20, 7) == 6" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder(20, 7)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder(20, divisor=7)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder(number=20, divisor=7)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder(divisor=7, number=20)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "ename": "SyntaxError", "evalue": "positional argument follows keyword argument (<ipython-input-7-9265fd4030d2>, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"<ipython-input-7-9265fd4030d2>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m remainder(number=20, 7)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n" ] } ], "source": [ "remainder(number=20, 7)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "remainder() got multiple values for argument 'number'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m<ipython-input-8-f2d03bd9e009>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mremainder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m20\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m7\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: remainder() got multiple values for argument 'number'" ] } ], "source": [ "remainder(20, number=7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "딕셔너리의 내용물을 사용해 remainder와 같은 함수를 호출하고 싶다면 \\*\\*연산자를 사용할 수 있다." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "my_kwargs = {\n", " 'number': 20,\n", " 'divisor': 7\n", "}" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "assert remainder(**my_kwargs) == 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\\*\\* 연산자를 위치 인자나 키워드 인자와 섞어서 함수를 호출할 수 있다. 다만 중복되는 인자가 없어야 한다." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "my_kwargs = {\n", " 'divisor': 7,\n", "}" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "assert remainder(number=20, **my_kwargs) == 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\\*\\* 연산자를 여러 번 사용할 수도 있다. 다만 여러 딕셔너리에 겹치는 키가 없어야 한다." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "my_kwargs = {\n", " 'number': 20,\n", "}" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "other_kwargs = {\n", " 'divisor': 7,\n", "}" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "assert remainder(**my_kwagrs, **other_kwargs) == 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "아무 키워드 인자나 받는 함수를 만들고 싶다면, 모든 키워드 인자를 dict에 모아주는 \\*\\*kwargs 라는 파라미터를 사용한다." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "def print_parameters(**kwargs):\n", " for key, value in kwargs.items():\n", " print(f'{key} = {value}')" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "alpha = 1.5\n", "beta = 9\n", "감마 = 4\n" ] } ], "source": [ "print_parameters(alpha=1.5, beta=9, 감마=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "키워드 인자가 제공하는 세가지 이점\n", "1. 코드를 처음 보는 사람들에게 함수 호출의 의미를 명확히 알려줄 수 있다.\n", "2. 함수 정의에서 디폴트 값을 지정할 수 있다." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "def flow_rate(weight_Diff, time_diff):\n", " return weight_diff / time_diff" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "weight_diff = 0.5\n", "time_diff = 3\n", "flow = flow_rate(weight_diff, time_diff)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.167 kg/s\n" ] } ], "source": [ "print(f'{flow:.3} kg/s')" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def flow_rate(weight_Diff, time_diff, period):\n", " return (weight_diff / time_diff) * period" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "flow_per_second = flow_rate(weight_diff, time_diff, 1)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.16666666666666666" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "flow_per_second" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "def flow_rate(weight_Diff, time_diff, period=1):\n", " return (weight_diff / time_diff) * period" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "flow_per_second = flow_rate(weight_diff, time_diff)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "flow_per_hour = flow_rate(weight_diff, time_diff, period=3600)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. 어떤 함수를 사용하던 기존 호출자에게는 하위 호환성을 제공하면서 함수 파라미터를 확장할 수 있는 방법을 제공한다는 것이다." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "def flow_rate(weight_Diff, time_diff, period=1, units_per_kg=1):\n", " return ((weight_diff / units_per_kg) / time_diff) * period" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "flow_per_hour = flow_rate(weight_diff, time_diff, period=3600, units_per_kg=2.2)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "272.72727272727275" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "flow_per_hour" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "선택적 인자를 위치인자로 지정하면 혼동을 야기할 수 있다.\n", "\n", "따라서 항상 키워드 인자를 사용하고 위치 인자를 절대 사용하지 않는 것" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 기억해야 할 내용\n", "- 함수 인자를 위치에 따라 지정할 수도 있고, 키워드를 사용해 지정할 수도 있다.\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 }