{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 12. 스트라이드와 슬라이스를 한 식에 함께 사용하지 말라" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬은 리스트[시작:끝:증가값]으로 일정한 간격을 두고 슬라이싱을 할 수 있는 스트라이드를 제공한다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['빨강', '노랑', '파랑']\n", "['주황', '초록', '자주']\n" ] } ], "source": [ "x = ['빨강', '주황', '노랑', '초록', '파랑', '자주']\n", "odds = x[::2]\n", "evens = x[1::2]\n", "print(odds)\n", "print(evens)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "스트라이드를 사용하는 구문은 버그를 야기할 수 있다." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b'esoognom'\n" ] } ], "source": [ "x = b'mongoose'\n", "y = x[::-1]\n", "print(y)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "司寿\n" ] } ], "source": [ "x = '寿司'\n", "y = x[::-1]\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "유니코드 문자열에서도 잘 되지만 utf-8로 인코딩한 문자열에서는 작동되지 않는다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b'\\xe5\\xaf\\xbf\\xe5\\x8f\\xb8'\n", "b'\\xb8\\x8f\\xe5\\xbf\\xaf\\xe5'\n" ] }, { "ename": "UnicodeDecodeError", "evalue": "'utf-8' codec can't decode byte 0xb8 in position 0: invalid start byte", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mUnicodeDecodeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m<ipython-input-4-a2081e8db6c2>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mz\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'utf-8'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mUnicodeDecodeError\u001b[0m: 'utf-8' codec can't decode byte 0xb8 in position 0: invalid start byte" ] } ], "source": [ "w = '寿司'\n", "x = w.encode('utf-8')\n", "print(x)\n", "y = x[::-1]\n", "print(y)\n", "z = y.decode('utf-8')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b'abcZYX123'\n", "b'321XYZcba'\n", "321XYZcba\n" ] } ], "source": [ "w = 'abcZYX123'\n", "x = w.encode('utf-8')\n", "print(x)\n", "y = x[::-1]\n", "print(y)\n", "z = y.decode('utf-8')\n", "print(z)\n", "# 아스키 코드 범위에 포함되면 문제가 없음." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-1 말고 다른 음수 증가값이 유용할까?" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['h', 'f', 'd', 'b']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']\n", "x[::2] # ['a', 'c', 'e', 'g']\n", "x[::-2] # ['h', 'f', 'd', 'b']" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['c', 'e', 'g']" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x[2::2]" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['g', 'e', 'c', 'a']" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x[-2::-2]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['g', 'e']" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x[-2:2:-2]" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x[2:2:-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "중요한 점은 슬라이싱 구문에 스트라이딩까지 들어가면 혼란스럽다.\n", "\n", "이런 문제를 방지하기 위해 시작값이나 끝값을 증가값과 함께 사용하지 말자." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "y = x[::2]\n", "z = y[1:-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "스트라이딩한 다음 슬라이싱을 하면 데이터를 한 번 더 얕게 복사하게 된다. (shallow copy)\n", "\n", "이 두 단계 연산에 필요한 시간과 메모리를 감당할 수 없다면 itertools 내장 모듈의 isliceㄷ 메서드를 고려하자." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 기억해야 할 내용\n", "- 슬라이스에 시작, 끝, 증가값을 함께 지정하면 코드의 의미를 혼동하기 쉽다.\n", "- 시작이나 끝 인덱스가 없는 슬라이스를 만들 때는 양수 증가값을 사용하라. 가급적 음수 증가값은 피하라.\n", "- 한 슬라이스 안에서 시작, 끝, 증가값을 함께 사용하지마라. 세 파라미터를 모두 써야하는 경우, 두번 대입을 사용하거나 itertools의 islice를 사용하라." ] } ], "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 }