аа. Документ Microsoft Word. Лабораторная работа ооп." , "cell type" "code", "execution count"
Скачать 44.82 Kb.
|
"\u001b[1;31mTypeError\u001b[0m: __init__() missing 3 required positional arguments: 'l', 'w', and 'h'" ] } ], "source": [ "t1 = KitchenTable()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "t1 = KitchenTable(2, 2, 0.7)\n", "t2 = DeskTable(1.5, 0.8, 0.75)\n", "t3 = KitchenTable(1, 1.2, 0.8)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t3.lenght" ] }, { "cell_type": "markdown", "metadata": { "collapsed": 'true' }, "source": [ "Несомненно можно создавать столы и от родительского класса Table. Однако он не будет, согласно неким родственным связям, иметь доступ к методам setPlaces() и square(). Точно также как объект класса KitchenTable не имеет доступа к единоличным атрибутам сестринского класса DeskTable" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "t4 = Table(1, 1, 0.5)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.2000000000000002" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t2.width * t2.lenght" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.2000000000000002" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t2.square()" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'Table' object has no attribute 'square'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m "\u001b[1;31mAttributeError\u001b[0m: 'Table' object has no attribute 'square'" ] } ], "source": [ "t4.square()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'KitchenTable' object has no attribute 'square'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m "\u001b[1;31mAttributeError\u001b[0m: 'KitchenTable' object has no attribute 'square'" ] } ], "source": [ "t3.square()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3.2. Полное переопределение метода надкласса\n", "Что если в подклассе нам не подходит код метода его надкласса. Допустим, мы вводим еще один класс столов, который является дочерним по отношению к DeskTable. Пусть это будут компьютерные столы, при вычислении рабочей поверхности которых надо отнимать заданную величину. Имеет смысл внести в этот новый подкласс его собственный метод square():" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class ComputerTable(DeskTable):\n", " def square(self, e):\n", " return self.width * self.lenght - e" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "При создании объекта типа ComputerTable по-прежнему требуется указывать параметры, так как интерпретатор в поисках конструктора пойдет по дереву наследования сначала в родителя, а потом в прародителя и найдет там метод __init__().\n", "\n", "Однако когда будет вызываться метод square(), то поскольку он будет обнаружен в самом ComputerTable, то метод square() из DeskTable останется невидимым, т. е. для объектов класса ComputerTable он окажется переопределенным." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.7" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ct = ComputerTable(2, 1, 1)\n", "ct.square(0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ИЛИ" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class ComputerTable(DeskTable):\n", " def square(self, e):\n", " return DeskTable.square(self) - e " ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.7" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ct = ComputerTable(2, 1, 1)\n", "ct.square(0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Допустим, в классе KitchenTable нам не нужен метод, поле places должно устанавливаться при создании объекта в конструкторе. В классе можно создать собсвенный конструктор с чистого листа, чем переопределить родительский:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class KitchenTable(Table):\n", " def __init__(self, l, w, h, p):\n", " self.length = l\n", " self.width = w\n", " self.height = h\n", " self.places = p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Однако, если дублируется почти весь конструктор надкласса, проще вызвать родительский конструктор, после чего дополнить своим кодом:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class KitchenTable(Table):\n", " def __init__(self, l, w, h, p):\n", " Table.__init__(self, l, w, h)\n", " self.places = p" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "tk = KitchenTable(2, 1.5, 0.7, 10)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tk.places" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.5" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tk.width " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3.3. Множественное наследование\n", "\n", "Для наследования от нескольких классав в определении класса-наследника достаточно указать в круглых скобках сразу несколько базовых классов через запятую.\n", "\n", "# Пример.\n", "\n", "Рассмотрим три класса:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class Classl: \n", " def funс1(self):\n", " print(\"Метод funс1() класса Classl\")\n", "\n", "class Class2(Classl): # Простое наследование\n", " def func2(self):\n", " print(\"Метод func2() класса Class2\")\n", "\n", "class Class3(Classl): # Простое наследование\n", " def funс1(self):\n", " print(\"Метод funс1() класса Class3\")\n", " def func2(self):\n", " print(\"Метод func2() класса Class3\")\n", " def func3(self):\n", " print(\"Метод func3() класса Class3\")\n", " def func4(self):\n", " print(\"Метод func4() класса Class3\")\n", "\n", "class Class4(Class2, Class3): # Множественное наследование\n", " def func4(self):\n", " print(\"Метод func4() класса Class4\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Метод funс1() класса Class3\n", "Метод func2() класса Class2\n", "Метод func3() класса Class3\n", "Метод func4() класса Class4\n" ] } ], "source": [ "c = Class4()\n", "c.funс1() \n", "c.func2() \n", "c.func3() \n", "c.func4() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Метод func1() определен в двух классах: class1 и ciass3. Так как вначале просматриваются все базовые классы, непосредственно указанные в определении текущего класса, метод func1() будет найден в классе class3 (поскольку он указан в числе базовых классов в определении Class4), а не в классе Class1.\n", "\n", "Метод func2() также определен в двух классах: Class2 и Class3. Так как класс Class2 стоит первым в списке базовых классов, то метод будет найден именно в нем. \n", "\n", "Чтобы наследовать метод из класса Class3, следует указать это явным образом:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Class4(Class2, Class3): # Множественное наследование\n", "# Наследуем func2() из класса Class3, а не из класса Class2\n", " func2 = Class3.func2\n", " def func4(self):\n", " print(\"Метод func4() класса Class4\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Метод funс1() класса Class3\n", "Метод func2() класса Class3\n", "Метод func3() класса Class3\n", "Метод func4() класса Class4\n" ] } ], "source": [ "c = Class4()\n", "c.funс1() \n", "c.func2() \n", "c.func3() \n", "c.func4() " ] }, { "cell_type": "markdown", "metadata": { "collapsed": 'true' }, "source": [ "# 4. Композиция\n", "\n", "Еще одной особенностью объектно-ориентированного программирования является возможность реализовывать так называемый композиционный подход. Заключается он в том, что есть класс-контейнер, он же агрегатор, который включает в себя вызовы других классов. В результате чего, что при создании объекта класса-контейнера, также создаются объекты включенных в него классов.\n", "\n", "Не следует путать композицию с наследованием, в том числе множественным. Наследование предполагает принадлежность к какой-то общности (похожесть), а композиция — формирование целого из частей. Наследуются атрибуты, т.е. возможности, другого класса, при этом объектов непосредственно родительского класса не создается. При композиции же класс-агрегатор создает объекты других классов.\n", "\n", "Рассмотрим на примере реализацию композиции в Python. Пусть, требуется написать программу, которая вычисляет площадь стен. При этом окна, двери, пол и потолок должны быть исключены.\n", "\n", "И так, комната – это прямоугольный параллелепипед, состоящий из шести прямоугольников. Его площадь представляет собой сумму площадей составляющих его прямоугольников. Площадь прямоугольника равна произведению его длины на ширину." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class WinDoor:\n", " def __init__(self, x, y):\n", " self.square = x * y " ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": 'true' }, "outputs": [], "source": [ "class Room:\n", " def __init__(self, x, y, z):\n", " self.square = 2 * z * (x + y)\n", " self.wd = []\n", " def addWD(self, w, h):\n", " self.wd.append(WinDoor(w, h))\n", " def workSurface(self):\n", " new_square = self.square\n", " for i in self.wd:\n", " new_square -= i.square\n", " return new_square" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "48.6\n", "44.6\n" ] } ], "source": [ "r1 = Room(6, 3, 2.7) \n", "print(r1.square)\n", "r1.addWD(1, 1) \n", "r1.addWD(1, 1)\n", "r1.addWD(1, 2)\n", "print(r1.workSurface())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Домашнее задание (базовое):" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Задание №1. \n", "\n", "Создать класс с двумя переменными. Добавить функцию вывода на экран и функцию изменения этих переменных. Добавить функцию, которая находит сумму значений этих переменных, и функцию которая находит наибольшее значение из этих двух переменных." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { |