{ "cells": [ { "cell_type": "markdown", "source": [ "# Пример создания класса «многочлен»\n", "Многочлен — это выражение вида\n", "$x^3 + 2x^2 - 10x + 5$. Будем хранить\n", "многочлены в виде списков коэффициентов:\n", "`[1, 2, -10, 5]`. Но лучше перевернем:\n", "`[5, -10, 2, 1]`. 5 — это коээфициент при\n", "$x^0$. -10 — это коэффициент при $x^1=x$.\n", "2 — коэффициент при $x^2$, 1 — коэффициент при\n", "$x^3$.\n", "\n", "Объекты класса многочлен хранят многочлены,\n", "эти объекты можно складывать, красиво\n", "распечатывать, искать значение в точке:\n", "$p(x) = x^3 + 2x^2 - 10x + 5$, тогда\n", "$p(0) = 5$, $p(1) = 1^3 + 2\\cdot 1^2 -\n", "10\\cdot1 + 5 = 1 + 2 - 10 + 5 = -2$.\n", "\n", "Класс `Poly` будет иметь одно поле (данные)\n", "со списком коэффициентов, и три указанных\n", "выше метода (распечатать, сложить, посчитать\n", "значение в точке. Давайте четвертый добавим —\n", "степень)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 1, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n", "2\n" ] } ], "source": [ "class Poly:\n", " # передаем список коэффициентов мн-на\n", " # игнорируем ситуацию, что старший коэф.\n", " # может быть 0\n", " def __init__(self, coefs):\n", " self.coefs = coefs\n", " # выдает степень многочлена.\n", " def deg(self):\n", " return len(self.coefs) - 1\n", "\n", "# Использование класса:\n", "p1 = Poly([5, -10, 2, 1])\n", "p2 = Poly([-1, 0, 1]) # -1 + 0*x + 1*x^2 = x^2-1\n", "\n", "print(p1.deg())\n", "print(p2.deg())" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Расширим наш класс, добавим печать, сложение,\n", "значение в точке:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 3, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5-10x^1+2x^2+x^3\n", "-1+x^2\n", "5\n", "-2\n" ] } ], "source": [ "class Poly:\n", " def __init__(self, coefs):\n", " self.coefs = coefs\n", "\n", " def deg(self):\n", " return len(self.coefs) - 1\n", "\n", " # посчитать значение в точке x\n", " def value(self, x):\n", " # n = 0\n", " # sum = 0\n", " # for coef in self.coefs:\n", " # sum += coef * x ** n\n", " # n += 1\n", "\n", " sum = 0\n", " for n, coef in enumerate(self.coefs):\n", " #n перебирает индексы 0, 1, 2, 3\n", " #coef перебирает элементы массива\n", " sum += coef * x ** n\n", " return sum\n", "\n", " # сделать красивую строку из многочлена\n", " def pretty(self):\n", " #сначала сделаем список одночленов\n", " #если коэффициенты [2, 0, 3, -1], то\n", " #получим [2, 0, 3x^2, -x^3].\n", "\n", " #add_coef(1, 'x') -> 'x'\n", " #add_coef(2, 'x') -> '2x'\n", " #add_coef(-3, 'x') -> '-3x'\n", " #add_coef(0, 'x') -> '0'\n", " def add_coef(c, var):\n", " if c == 0:\n", " return '0'\n", " if c == 1:\n", " return var\n", " if c == -1:\n", " return '-' + var\n", " return f'{c}{var}'\n", "\n", " #add_polys('2x', '3x^2') -> '2x+3x^2'\n", " #add_polys('2x', '-3x^2') -> '2x-3x^2'\n", " #add_polys('0', '-3x^2') -> '-3x^2'\n", " def add_polys(m1, m2):\n", " if m1 == '0':\n", " return m2\n", " if m2 == '0':\n", " return m1\n", " if m2[0] == '-':\n", " return m1 + m2\n", " return m1 + '+' + m2\n", "\n", " # [4, 5, 3, 2] -> 4 + 5x + 3x^2\n", " result = str(self.coefs[0]) # '4'\n", " # перебираем список [5, 3, 2]\n", " for d, coef in enumerate(self.coefs[1:]):\n", " result = add_polys(result, add_coef(coef, f'x^{d+1}'))\n", " return result\n", "\n", "# Сэкономим на сложении многочленов. Проверим,\n", "# что есть:\n", "\n", "p1 = Poly([5, -10, 2, 1])\n", "p2 = Poly([-1, 0, 1]) # -1 + 0*x + 1*x^2 = x^2-1\n", "\n", "print(p1.pretty())\n", "print(p2.pretty())\n", "\n", "print(p1.value(0)) # должно быть 5\n", "print(p1.value(1)) # должно быть -2" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 4, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5-10x^1+2x^2+x^3\n", "5-10x^1+2x^2+x^3+42x^4\n" ] } ], "source": [ "# пример кода с пробемами:\n", "a = [5, -10, 2, 1]\n", "p1 = Poly(a)\n", "print(p1.pretty())\n", "a.append(42) # a = [5, -10, 2, 1, 42]\n", "print(p1.pretty())" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Многочлен p1 изменился, потому что он хранит\n", "ссылку на список, и если кто-то этот список\n", "меняет, многочлену тоже приходится меняться.\n", "\n", "Исправляем:\n", "\n", "```\n", "class Poly:\n", " def __init__(self, coefs):\n", " # теперь список копируется\n", " # coefs.copy() - требовал бы, что\n", " # coefs это список.\n", " self.coefs = list(coefs)\n", "\n", " ...\n", "\n", "p1 = Poly( (10, 20, 30) ) # можно передать tuple\n", "p1 = Poly(range(10)) # любое перечисление\n", "```" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 5, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4+5x^1+6x^2\n" ] } ], "source": [ "p1.coefs = [4, 5, 6]\n", "print(p1.pretty())" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Такое ручное изменение содержимого объекта\n", "никогда не приветствуется. (принцип инкапсуляции),\n", "считается, что мы не знаем, как устроены объекты.\n", "Как хранятся коэффициенты, может, они вообще\n", "не в списке хранятся. Любое действие с объектом\n", "принято делать через методы.\n", "Чтобы явно показать, что мы не хотим, чтобы\n", "кто-то писал `p1.coefs`, надо поле `coefs` назвать\n", "с подчеркивания: `_coefs`. Все, что начинается\n", "с подчеркивания, принято вызывать только внутри\n", "класса." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "class Poly:\n", " def __init__(self, coefs):\n", " self._coefs = coefs\n", "\n", " def deg(self):\n", " return len(self._coefs) - 1\n", "\n", " # посчитать значение в точке x\n", " def value(self, x):\n", " # n = 0\n", " # sum = 0\n", " # for coef in self.coefs:\n", " # sum += coef * x ** n\n", " # n += 1\n", "\n", " sum = 0\n", " for n, coef in enumerate(self._coefs):\n", " #n перебирает индексы 0, 1, 2, 3\n", " #coef перебирает элементы массива\n", " sum += coef * x ** n\n", " return sum\n", "\n", " # сделать красивую строку из многочлена\n", " def pretty(self):\n", " #сначала сделаем список одночленов\n", " #если коэффициенты [2, 0, 3, -1], то\n", " #получим [2, 0, 3x^2, -x^3].\n", "\n", " #add_coef(1, 'x') -> 'x'\n", " #add_coef(2, 'x') -> '2x'\n", " #add_coef(-3, 'x') -> '-3x'\n", " #add_coef(0, 'x') -> '0'\n", " def add_coef(c, var):\n", " if c == 0:\n", " return '0'\n", " if c == 1:\n", " return var\n", " if c == -1:\n", " return '-' + var\n", " return f'{c}{var}'\n", "\n", " #add_polys('2x', '3x^2') -> '2x+3x^2'\n", " #add_polys('2x', '-3x^2') -> '2x-3x^2'\n", " #add_polys('0', '-3x^2') -> '-3x^2'\n", " def add_polys(m1, m2):\n", " if m1 == '0':\n", " return m2\n", " if m2 == '0':\n", " return m1\n", " if m2[0] == '-':\n", " return m1 + m2\n", " return m1 + '+' + m2\n", "\n", " # [4, 5, 3, 2] -> 4 + 5x + 3x^2\n", " result = str(self._coefs[0]) # '4'\n", " # перебираем список [5, 3, 2]\n", " for d, coef in enumerate(self._coefs[1:]):\n", " if d == 0:\n", " var = 'x'\n", " else:\n", " var = f'x^{d + 1}'\n", " result = add_polys(add_coef(coef, var), result)\n", " return result\n", "\n", "# Сэкономим на сложении многочленов. Проверим,\n", "# что есть:\n", "\n", "p1 = Poly([5, -10, 2, 1])\n", "p2 = Poly([-1, 0, 1]) # -1 + 0*x + 1*x^2 = x^2-1\n", "\n", "print(p1.pretty())\n", "print(p2.pretty())\n", "\n", "print(p1.value(0)) # должно быть 5\n", "print(p1.value(1)) # должно быть -2\n", "\n", "print(p1._coefs) # так не делаем. Имя с _" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 0 }