{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "***\n", "# 16. 람다 함수\n", "***\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 1. 람다(lambda) 함수 정의\n", "---\n", "- 람다(lambda) 함수 (or 축약 함수): https://wikidocs.net/64\n", " - 일반적인 함수를 한 줄의 문(Statement)으로 정의할 수 있는 새로운 함수 정의 리터럴\n", " - 함수 몸체에는 식(expression)만이 올 수 있다. \n", " - 대부분의 경우 함수 이름을 정의하지 않으면서 일회성으로 활용할 함수를 정의할 때 활용\n", " - 구문(syntax)\n", " - lambda 콤마로 구분된 인수들: 식(expression)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-1 람다 함수 정의 예" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 인수가 한 개 있는 람다 함수" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "f = lambda x: x + 1\n", "print(f(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 인수가 두 개 있는 람다 함수를 지니는 변수 지정 및 함수 호출" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n" ] } ], "source": [ "g = lambda x, y: x + y\n", "print(g(1, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 기본 인수를 지니는 람다 함수 정의" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11\n", "15\n" ] } ], "source": [ "incr = lambda x, inc = 1: x + inc\n", "print(incr(10))#inc 기본 인수 값으로 1 사용\n", "print(incr(10, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 가변 인수를 지니는 람다 함수 정의" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(2, 3, 4, 5)\n", "\n", "\n" ] } ], "source": [ "vargs = lambda x, *args: args\n", "print(vargs(1, 2, 3, 4, 5))\n", "\n", "# 이전 jupyter notebook 참고; \"넣어주는 인수 값들 중 일반 인수에 할당되는 값을 제외한 나머지 값들을 지닌 튜플 객체가 할당된다.\"\n", "print(type(vargs))\n", "print(type(vargs(1, 2, 3, 4, 5)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-2 람다 함수 사용하기" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[60, 44, 30, 18, 8, 0, -6, -10, -12, -12, -10, -6, 0, 8, 18, 30, 44, 60, 78, 98]\n", "[-1000, -729, -512, -343, -216, -125, -64, -27, -8, -1, 0, 1, 8, 27, 64, 125, 216, 343, 512, 729]\n" ] } ], "source": [ "def f1(x):\n", " return x * x + 3 * x - 10\n", "\n", "def f2(x):\n", " return x * x * x\n", "\n", "def g(func):\n", " return [func(x) for x in range(-10, 10)]\n", "\n", "print(g(f1))\n", "print(g(f2))" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[60, 44, 30, 18, 8, 0, -6, -10, -12, -12, -10, -6, 0, 8, 18, 30, 44, 60, 78, 98]\n", "[-1000, -729, -512, -343, -216, -125, -64, -27, -8, -1, 0, 1, 8, 27, 64, 125, 216, 343, 512, 729]\n" ] } ], "source": [ "def g(func):\n", " return [func(x) for x in range(-10, 10)]\n", "\n", "print(g(lambda x: x * x + 3 * x - 10))\n", "print(g(lambda x: x * x * x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 람다 함수를 사용하는 코드 예제" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0. add\n", "1. sub\n", "2. mul\n", "3. div\n", "4. quit\n", "Select menu:1\n", "First operand:10\n", "Second operand:2\n", "Result = 8\n", "\n", "0. add\n", "1. sub\n", "2. mul\n", "3. div\n", "4. quit\n", "Select menu:2\n", "First operand:10\n", "Second operand:10\n", "Result = 100\n", "\n", "0. add\n", "1. sub\n", "2. mul\n", "3. div\n", "4. quit\n", "Select menu:4\n" ] } ], "source": [ "# 더하기, 빼기, 곱하기, 나누기에 해당하는 람다 함수 리스트 정의\n", "func_list = [\n", " lambda x, y: x + y, \n", " lambda x, y: x - y, \n", " lambda x, y: x * y, \n", " lambda x, y: x / y\n", "]\n", "\n", "def menu():\n", " print(\"0. add\")\n", " print(\"1. sub\")\n", " print(\"2. mul\")\n", " print(\"3. div\")\n", " print(\"4. quit\")\n", " return int(input('Select menu:'))\n", "\n", "while 1:\n", " sel = menu() \n", " if sel < 0 or sel > len(func_list): \n", " continue\n", " if sel == len(func_list): \n", " break\n", " x = int(input('First operand:'))\n", " y = int(input('Second operand:')) \n", " print('Result =', func_list[sel](x,y), end=\"\\n\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 2 람다 함수의 활용\n", "***\n", "- map, filter, reduce 내장 함수\n", " - 첫번째 인자: function\n", " - 첫번째 인자는 일반적으로 람다 함수를 인자로 받는다.\n", " - 두번째 인자: 시퀀스 자료형 (문자열, 리스트, 튜플)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2-1 map 내장 함수\n", "- map(function, seq)\n", " - (python2) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과를 동일 시퀀스 자료형으로 반환한다.\n", " - (python3) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 원소를 지닌 map 객체를 반환한다.\n", " - 이후 동일한 자료형으로 다시 변환 필요" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "def f(x):\n", " return x * x\n", "\n", "X = [1, 2, 3, 4, 5]\n", "m = map(f, X)\n", "print(type(m))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4, 9, 16, 25]\n" ] } ], "source": [ "def f(x):\n", " return x * x\n", "\n", "X = [1, 2, 3, 4, 5]\n", "Y = list(map(f, X)) \n", "\n", "print(Y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- map 내장 함수를 사용하지 않을 때 코드" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4, 9, 16, 25]\n" ] } ], "source": [ "def f(x):\n", " return x * x\n", "\n", "X = [1, 2, 3, 4, 5]\n", "\n", "Y = []\n", "for x in X:\n", " y = f(x)\n", " Y.append(y)\n", "print(Y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- map과 람다 함수를 동시에 사용하는 코드 (가장 추천하는 코드)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4, 9, 16, 25]\n" ] } ], "source": [ "X = [1, 2, 3, 4, 5]\n", "print(list(map(lambda x: x * x, X)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- range(10)의 모든 값 x에 대해 f = x \\* x + 4 * x + 5의 계산 결과를 리스트로 구함" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 10, 17, 26, 37, 50, 65, 82, 101, 122]\n" ] } ], "source": [ "Y = list(map(lambda x: x * x + 4 * x + 5, range(10)))\n", "print(Y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 각 단어들의 길이 리스트" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[5, 6, 11]\n" ] } ], "source": [ "y = list(map(lambda x: len(x), [\"Hello\", \"Python\", \"Programming\"]))\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2-2 filter 내장 함수\n", "- filter(function, seq)\n", " - (python2) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과가 참인 원소값들만을 동일 시퀀스 자료형으로 반환한다.\n", " - (python3) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과가 참인 원소값들만을 지닌 filter 객체를 반환한다.\n", " - 이후 동일한 자료형으로 다시 변환 필요" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 34]\n" ] } ], "source": [ "print(list(filter(lambda x: x > 2, [1, 2, 3, 34])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 위 코드는 아래와 동일하다." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 34]\n" ] } ], "source": [ "y = []\n", "for x in [1, 2, 3, 34]:\n", " if x > 2:\n", " y.append(x)\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 주어진 시퀀스 내에 있는 정수중 홀수만 필터링" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 3, 5]\n" ] } ], "source": [ "print(list(filter(lambda x: x % 2, [1, 2, 3, 4, 5, 6])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 주어진 시퀀스 내에 있는 정수중 짝수만 필터링" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 4, 6]\n" ] } ], "source": [ "print(list(filter(lambda x: x % 2 - 1, [1, 2, 3, 4, 5, 6])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 특정 범위에 있는 정수만 필터링" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 3, 4]\n" ] } ], "source": [ "def F():\n", " x = 1\n", " print(list(filter(lambda a: a > x, range(-5, 5))))\n", " \n", "F()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## python2 --> python3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(python2)\n", "- map과 filter의 결과는 주어진 seq 자료형과 동일함" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(python3)\n", "- filter, map은 iterator 객체인 filter, map을 각각 리턴함\n", "- 참고\n", " - https://docs.python.org/3/library/functions.html#map\n", " - https://docs.python.org/3/library/functions.html#filter\n", " - https://stackoverflow.com/questions/12319025/filters-in-python3" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n" ] } ], "source": [ "print(filter(lambda x: x > 2, [1, 2, 3, 34]))\n", "print(filter(lambda x: x > 2, (1, 2, 3, 34)))\n", "print(filter(lambda x: x < 'a', 'abcABCdefDEF'))" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 34]\n", "(3, 34)\n", "['A', 'B', 'C', 'D', 'E', 'F']\n" ] } ], "source": [ "print(list(filter(lambda x: x > 2, [1, 2, 3, 34])))\n", "print(tuple(filter(lambda x: x > 2, (1, 2, 3, 34))))\n", "print(list(filter(lambda x: x < 'a', 'abcABCdefDEF')))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2-4 reduce 내장 함수\n", "- reduce (function, seq[, initial])\n", " - 파이썬3에서 reduce() 내장 함수 지원하지 않음.\n", " - 파이썬3에서 reduce() 함수를 사용하려면 다음의 라인을 상단에 추가해주어야 한다.\n", " - from functools import reduce\n", " - seq 시퀀스 자료형이 지닌 원소값들에 대해 function 함수를 적용하면서 하나의 값으로 축약한다.(reduce returns a single value.)\n", " - 첫번째 인자인 function 함수는 반드시 두 개의 인자 (예를 들어, x, y)를 받아야 한다.\n", " - seq 시퀀스 자료형의 각 원소값들은 각 단계별로 y에 순차적으로 들어간다. \n", " - 함수가 수행된 값은 각 단계별로 x에 순차적으로 들어간다.\n", " - 추가적으로 제공가능한 세번째 인자인 initial은 첫번째 단계에 x에 할당할 초기값으로 사용된다. \n", " - 참고: https://www.python-course.eu/python3_lambda.php" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "from functools import reduce" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "15\n" ] } ], "source": [ "print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "| 단계 | x | y | reduce |\n", "|-----|---|---|---------|\n", "| 1 | 0 | 1 | 1 |\n", "| 2 | 1 | 2 | 3 |\n", "| 3 | 3 | 3 | 6 |\n", "| 4 | 6 | 4 | 10 |\n", "| 5 | 10| 5 | 15 | " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- initial 값 할당" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "115\n" ] } ], "source": [ "print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5], 100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 1부터 10까지 각 수에 대한 제곱값을 모두 더한 결과 구함" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "385\n" ] } ], "source": [ "print(reduce(lambda x, y: x + y * y, range(1, 11), 0))" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "385\n" ] } ], "source": [ "x = 0\n", "for y in range(1, 11):\n", " x = x + y * y\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 문자열 순서 뒤집기" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "edcba\n" ] } ], "source": [ "print(reduce(lambda x, y: y + x, 'abcde'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "| 단계 | x | y | reduce |\n", "|-----|---|---|---------|\n", "| 1 | '' | 'a' | 'a' |\n", "| 2 | 'a' | 'b' | 'ba' |\n", "| 3 | 'ba' | 'c' | 'cba' |\n", "| 4 | 'cba' | 'd' | 'dcba' |\n", "| 5 | 'dcba' | 'e' | 'edcba' | " ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The maximum element of the list is : 6\n" ] } ], "source": [ "lis = [1, 3, 5, 6, 2] \n", "\n", "print(\"The maximum element of the list is : \",end=\"\") \n", "print(reduce(lambda a, b: a if a > b else b, lis)) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

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

" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 1 }