Главная страница

аа. Документ Microsoft Word. Лабораторная работа ооп." , "cell type" "code", "execution count"


Скачать 44.82 Kb.
НазваниеЛабораторная работа ооп." , "cell type" "code", "execution count"
Дата24.01.2021
Размер44.82 Kb.
Формат файлаdocx
Имя файлаДокумент Microsoft Word.docx
ТипЛабораторная работа
#171014
страница2 из 4
1   2   3   4
\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mp2\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mPerson\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",

"\u001b[1;31mTypeError\u001b[0m: __init__() missing 2 required positional arguments: 'n' and 's'"

]

}

],

"source": [

"p2 = Person()"

]

},

{

"cell_type": "code",

"execution_count": 30,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"Sam Baker\n"

]

}

],

"source": [

"p2 = Person(\"Sam\", \"Baker\")\n",

"print(p2.name, p2.surname)"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Однако бывает, что надо допустить создание объекта, даже если никакие данные в конструктор не передаются. В таком случае параметрам конструктора класса задаются значения по умолчанию:"

]

},

{

"cell_type": "code",

"execution_count": 31,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class Rectangle:\n",

" def __init__(self, w = 0.5, h = 1):\n",

" self.width = w\n",

" self.height = h\n",

" def square(self):\n",

" return self.width * self.height"

]

},

{

"cell_type": "code",

"execution_count": 32,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"10\n",

"0.5\n",

"3\n",

"2.0\n"

]

}

],

"source": [

"rec1 = Rectangle(5, 2)\n",

"rec2 = Rectangle()\n",

"rec3 = Rectangle(3)\n",

"rec4 = Rectangle(h = 4)\n",

"\n",

"print(rec1.square())\n",

"print(rec2.square())\n",

"print(rec3.square())\n",

"print(rec4.square())"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Конструктор и деструктор\n",

"\n",

"Помимо конструктора объектов в языках программирования есть обратный ему метод – деструктор. Он вызывается для уничтожения объекта.\n",

"\n",

"В языке программирования Python объект уничтожается, когда исчезают все связанные с ним переменные или им присваивается другое значение, в результате чего связь со старым объектом теряется. Удалить переменную можно с помощью команды языка del.\n",

"\n",

"В классах Python функцию деструктора выполняет метод $__del__()$."

]

},

{

"cell_type": "code",

"execution_count": 33,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class Student:\n",

" \n",

" def __init__(self, name, surname, position=1):\n",

" self.name = name\n",

" self.surname = surname\n",

" self.position = position\n",

" \n",

" def display(self):\n",

" return self.name, self.surname, self.position\n",

" \n",

" def __del__(self):\n",

" print (\"Goodbye %s %s\" %(self.name, self.surname))"

]

},

{

"cell_type": "code",

"execution_count": 34,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"p1 = Student('big', 'dude', 3) \n",

"p2 = Student('small', 'croon', 4)\n",

"p3 = Student('neutral', 'guy', 5)"

]

},

{

"cell_type": "code",

"execution_count": 35,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"('big', 'dude', 3)\n",

"('small', 'croon', 4)\n",

"('neutral', 'guy', 5)\n"

]

}

],

"source": [

"print (p1.display())\n",

"print (p2.display())\n",

"print (p3.display())"

]

},

{

"cell_type": "code",

"execution_count": 36,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"Goodbye small croon\n"

]

}

],

"source": [

"del p2"

]

},

{

"cell_type": "code",

"execution_count": 37,

"metadata": {},

"outputs": [

{

"ename": "NameError",

"evalue": "name 'p2' is not defined",

"output_type": "error",

"traceback": [

"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",

"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",

"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mp2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdisplay\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",

"\u001b[1;31mNameError\u001b[0m: name 'p2' is not defined"

]

}

],

"source": [

"print (p2.display())"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Специальные методы Python"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"В Python есть ряд зарезервированных имен методов создаваемого класса - специальные (или стандартные) методы.\n",

"\n",

"Более подробную информацию о них вы можете найти в соответствующей документации по Python: https://docs.python.org/3/reference/datamodel.html\n",

"\n",

"Например:\n",

"\n",

"$__bool__()$\n",

"\n",

"Возвращает True или False.\n",

"\n",

"$__call__()$\n",

"\n",

"Позволяет использовать объект как функцию, т.е. его можно вызвать.\n",

"\n",

"$__len__()$\n",

"\n",

"Чаще всего реализуется в коллекциях и сходными с ними по логике работы типами, которые позволяют хранить наборы данных. Для списка (list) __len__() возвращает количество элементов в списке, для строки – количество символов в строке. Вызывается функцией len(), встроенной в язык Python."

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Метод $__setattr__()$\n",

"\n",

"В Python атрибуты объекту можно назначать за пределами класса:"

]

},

{

"cell_type": "code",

"execution_count": 38,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class A:\n",

" def __init__(self, v):\n",

" self.field1 = v"

]

},

{

"cell_type": "code",

"execution_count": 39,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"10 20\n"

]

}

],

"source": [

"a = A(10)\n",

"a.field2 = 20\n",

"print(a.field1, a.field2)"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Если такое поведение нежелательно, его можно запретить с помощью метода перегрузки оператора присваивания атрибуту $__setattr__()$:"

]

},

{

"cell_type": "code",

"execution_count": 40,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class A:\n",

" def __init__(self, v):\n",

" self.field1 = v\n",

" def __setattr__(self, attr, value):\n",

" if attr == 'field1':\n",

" self.__dict__[attr] = value\n",

" else:\n",

" raise AttributeError('Произошло обращение к несуществующему отребуту!')"

]

},

{

"cell_type": "code",

"execution_count": 41,

"metadata": {},

"outputs": [

{

"data": {

"text/plain": [

"15"

]

},

"execution_count": 41,

"metadata": {},

"output_type": "execute_result"

}

],

"source": [

"a = A(15)\n",

"a.field1"

]

},

{

"cell_type": "code",

"execution_count": 42,

"metadata": {},

"outputs": [

{

"ename": "AttributeError",

"evalue": "Произошло обращение к несуществующему отребуту!",

"output_type": "error",

"traceback": [

"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",

"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",

"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfield2\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m30\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",

"\u001b[1;32m\u001b[0m in \u001b[0;36m__setattr__\u001b[1;34m(self, attr, value)\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__dict__\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mattr\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Произошло обращение к несуществующему отребуту!'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",

"\u001b[1;31mAttributeError\u001b[0m: Произошло обращение к несуществующему отребуту!"

]

}

],

"source": [

"a.field2 = 30"

]

},

{

"cell_type": "code",

"execution_count": 43,

"metadata": {},

"outputs": [

{

"ename": "AttributeError",

"evalue": "'A' object has no attribute 'field2'",

"output_type": "error",

"traceback": [

"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",

"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",

"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfield2\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",

"\u001b[1;31mAttributeError\u001b[0m: 'A' object has no attribute 'field2'"

]

}

],

"source": [

"a.field2"

]

},

{

"cell_type": "code",

"execution_count": 44,

"metadata": {},

"outputs": [

{

"data": {

"text/plain": [

"{'field1': 15}"

]

},

"execution_count": 44,

"metadata": {},

"output_type": "execute_result"

}

],

"source": [

"a.__dict__"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Метод __setattr__(), если он присутствует в классе, вызывается всегда, когда какому-либо атрибуту выполняется присваивание. Обратите внимание, что присвоение несуществующему атрибуту также обозначает его добавление к объекту.\n",

"\n",

"Когда создается объект a, в конструктор передается число 15. Здесь для объекта заводится атрибут field1. Факт попытки присвоения ему значения тут же отправляет интерпретатор в метод __setattr__(), где проверяется соответствует ли имя атрибута строке 'field1'. Если так, то атрибут и соответствующее ему значение добавляется в словарь атрибутов объекта.\n",

"\n",

"Нельзя в __setattr__() написать просто self.field1 = value, так как это приведет к новому рекурсивному вызову метода __setattr__(). Поэтому поле назначается через словарь __dict__, который есть у всех объектов, и в котором хранятся их атрибуты со значениями.\n",

"\n",

"Если параметр attr не соответствует допустимым полям, то искусственно возбуждается исключение AttributeError. Мы это видим, когда в основной ветке пытаемся обзавестись полем field2."

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Пример №1. Числа Фибоначчи\n",

"\n",

"Последовательность чисел Фибоначчи задаётся рекуррентным выражением:\n",

"\n",

"$$ F_n = \\begin{cases}\n",

" 0, n = 0, \\\\\n",

" 1, n = 1, \\\\\n",

" F_{n-1}+F_{n-2}, n > 1.\n",

" \\end{cases} $$\n",

"\n",

"Что даёт следующую последовательность {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …}."

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Один из способов решения, который может показаться логичным и эффективным, — решение с помощью рекурсии:"

]

},

{

"cell_type": "code",

"execution_count": 45,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"def Fibonacci_Recursion(n):\n",

" if n == 0:\n",

" return 0\n",

" if n == 1:\n",

" return 1\n",

" return Fibonacci_Recursion (n-1) + Fibonacci_Recursion (n-2)"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Используя такую функцию, мы будем решать задачу «с конца» — будем шаг за шагом уменьшать n, пока не дойдем до известных значений.\n",

"\n",

"Но, как мы видели ранее эта реализация многократно повторяет решение одних и тех же задач. Это связано с тем, что одни и те же промежуточные данные вычисляются по несколько раз, а число операций нарастает с той же скоростью, с какой растут числа Фибоначчи — экспоненциально.\n",

"\n",

"Один из выходов из данной ситуации — сохранение уже найденных промежуточных результатов с целью их повторного использования (кеширование). Причём кеш должен храниться во внешней области памяти."

]

},

{

"cell_type": "code",

"execution_count": 46,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"def Fibonacci_Recursion_cache(n, cache):\n",

" if n == 0:\n",

" return 0\n",

" if n == 1:\n",

" return 1\n",

" if cache[n] > 0:\n",

" return cache[n]\n",

" cache[n] = Fibonacci_Recursion_cache (n-1, cache) + Fibonacci_Recursion_cache (n-2, cache)\n",

" return cache[n]"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Приведенное решение достаточно эффективно (за исключением накладных расходов на вызов функций). Но можно поступить ещё проще:"

]

},

{

"cell_type": "code",

"execution_count": 1,

"metadata": {},

"outputs": [],

"source": [

"def Fibonacci(n):\n",

" \n",

" fib = [0]*max(2,n)\n",

" fib[0] = 1\n",

" fib[1] = 1\n",

" for i in range(2, n):\n",

" fib[i] = fib[i - 1] + fib[i - 2]\n",

" \n",

" return fib[n-1]"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Такое решение можно назвать решением «с начала» — мы первым делом заполняем известные значения, затем находим первое неизвестное значение, потом следующее и т.д., пока не дойдем до нужного.\n",

"\n",

"Так и работает динамическое программирование: сначала решили все подзадачи (нашли все F[i] для i < n), затем, зная решения подзадач, нашли решение исходной задачи."

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Упражнение №1\n",

"\n",

"Создайте класс для вычисления чисел Фибоначчи. Каждое число фибоначи является объектом этого класса, которое имеет атрибуты: значение и номер. Используйте функции для инициализации (вычисления) чисел Фибоначчи как сторонние по отношению к этому классу."

]

},

{

"cell_type": "code",

"execution_count": ‘null’

"metadata": {},

"outputs": [],

"source": []

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Упражнение №2\n",

"\n",

"Поместите функции для вычисления чисел Фибоначчи внутрь созданного класса как статические функции."

]

},

{

"cell_type": "code",

"execution_count": 21,

"metadata": {},

"outputs": [],

"source": []

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# Упражнение №3\n",

"\n",

"Перегрузите опарации сложения, вычитания, умножения и деления для созданного класса как операции с номерами чисел Фибоначи."

]

},

{

"cell_type": "code",

"execution_count": ‘null’

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": []

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# 1.5. Инкапсуляция\n",

"Под инкапсуляцией в объектно-ориентированном программировании понимается упаковка данных и методов для их обработки вместе, т. е. в классе. В Python инкапсуляция реализуется как на уровне классов, так и объектов. В ряде других языков, например в Java, под инкапсуляцией также понимают сокрытие свойств и методов, в результате чего они становятся приватными. Это значит, что доступ к ним ограничен либо пределами класса, либо модуля.\n",

"\n",

"В Python подобной инкапсуляции нет, хотя существует способ ее имитировать. Перед тем как выяснять, как это делается, надо понять, зачем вообще что-то скрывать.\n",

"\n",

"Дело в том, что классы бывают большими и сложными. В них может быть множество вспомогательных полей и методов, которые не должны использоваться за его пределами. Они просто для этого не предназначены. Они своего рода внутренние шестеренки, обеспечивающие нормальную работу класса.\n",

"\n",

"Кроме того, в других языках программирования хорошей практикой считается сокрытие всех полей объектов, чтобы уберечь их от прямого присвоения значений из основной ветки программы. Их значения можно изменять и получать только через вызовы методов, специально определенных для этих целей.\n",

"\n",

"Например, если надо проверять присваиваемое полю значение на корректность, то делать это каждый раз в основном коде программы будет неправильным. Проверочный код должен быть помещен в метод, который получает данные, для присвоения полю. А само поле должно быть закрыто для доступа из вне класса. В этом случае ему невозможно будет присвоить недопустимое значение.\n",

"\n",

"Часто намеренно скрываются поля самого класса, а не его объектов. Например, если класс имеет счетчик своих объектов, то необходимо исключить возможность его случайного изменения из вне. Рассмотрим пример с таким счетчиком на языке Python."

]

},

{

"cell_type": "code",

"execution_count": 1,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class B:\n",

" count = 0\n",

" def __init__(self):\n",

" B.count += 1\n",

" def __del__(self):\n",

" B.count -= 1"

]

},

{

"cell_type": "code",

"execution_count": 2,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"3\n",

"3\n",

"2\n"

]

}

],

"source": [

"a = B()\n",

"b = B()\n",

"с = B()\n",

"print(b.count)\n",

"print(B.count) \n",

"del a\n",

"print(B.count) "

]

},

{

"cell_type": "code",

"execution_count": 4,

"metadata": {},

"outputs": [

{

"data": {

"text/plain": [

"2"

]

},

"execution_count": 4,

"metadata": {},

"output_type": "execute_result"

}

],

"source": [

"b.count"

]

},

{

"cell_type": "code",

"execution_count": 5,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"1\n"

]

}

],

"source": [

"B.count -= 1\n",

"print(B.count)"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"# 2. Полиморфизм\n",

"Полиморфизм в объектно-ориентированном программировании – это возможность обработки разных типов данных, т. е. принадлежащих к разным классам, с помощью \"одно и той же\" функции, или метода. На самом деле одинаковым является только имя метода, его исходный код зависит от класса. Кроме того, результаты работы одноименных методов могут существенно различаться. Поэтому в данном контексте под полиморфизмом понимается множество форм одного и того же слова – имени метода.\n",

"\n",

"Например, два разных класса содержат метод total, однако инструкции каждого предусматривают совершенно разные операции. Так в классе T1 – это прибавление 10 к аргументу, в T2 – подсчет длины строки символов. В зависимости от того, к объекту какого класса применяется метод total, выполняются те или иные инструкции."

]

},

{

"cell_type": "code",

"execution_count": 8,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class T1:\n",

" n=10\n",

" def total(self, N):\n",

" self.total = int(self.n) + int(N)\n",

" \n",

"class T2:\n",

" def total(self,s):\n",

" self.total = len(str(s))"

]

},

{

"cell_type": "code",

"execution_count": 9,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"55\n",

"2\n"

]

}

],

"source": [

"t1 = T1()\n",

"t2 = T2()\n",

"t1.total(45)\n",

"t2.total(45)\n",

"print(t1.total) \n",

"print(t2.total) "

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Как видно полиморфизмом обладают классы связанные наследованием. У каждого может быть свой метод __init__() или square() или какой-нибудь другой. Какой именно из методов square() вызывается, и что он делает, зависит от принадлежности объекта к тому или иному классу.\n",

"\n",

"Однако классы не обязательно должны быть связанны наследованием. Полиморфизм как один из ключевых элементов ООП существует независимо от наследования. Классы могут быть не родственными, но иметь одинаковые методы.\n",

"\n",

"Полиморфизм дает возможность реализовывать так называемые единые интерфейсы для объектов различных классов. Например, разные классы могут предусматривать различный способ вывода той или иной информации объектов. Однако одинаковое название метода вывода позволит не запутать программу, сделать код более ясным.\n",

"\n",

"Рассмотрим пример полиморфизма на еще одном методе, который перегружает функцию print().\n",

"\n",

"Если вы создадите объект собственного класса, а потом попробуете вывести его на экран, то получите информацию о классе объекта и его адрес в памяти. Такое поведение функции print() по-умолчанию по отношению к пользовательским классам запрограммировано на самом верхнем уровне иерархии, где-то в суперклассе, от которого неявно наследуются все остальные."

]

},

{

"cell_type": "code",

"execution_count": 10,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class A:\n",

" def __init__(self, v1, v2):\n",

" self.field1 = v1\n",

" self.field2 = v2"

]

},

{

"cell_type": "code",

"execution_count": 11,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"<__main__.A object at 0x0000021DDCE084E0>\n"

]

}

],

"source": [

"a = A(3, 4)\n",

"print(a)"

]

},

{

"cell_type": "markdown",

"metadata": {},

"source": [

"Если же мы хотим, чтобы, когда объект передается функции print(), выводилась какая-нибудь другая более полезная информация, то в класс надо добавить специальный метод __str__(). Этот метод должен обязательно возвращать строку, которую будет выводить функция print():"

]

},

{

"cell_type": "code",

"execution_count": 12,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class A:\n",

" def __init__(self, v1, v2):\n",

" self.field1 = v1\n",

" self.field2 = v2\n",

" def __str__(self):\n",

" return str(self.field1) + \" \" + str(self.field2)"

]

},

{

"cell_type": "code",

"execution_count": 13,

"metadata": {},

"outputs": [

{

"name": "stdout",

"output_type": "stream",

"text": [

"3 4\n"

]

}

],

"source": [

"a = A(3, 4)\n",

"print(a)"

]

},

{

"cell_type": "markdown",

"metadata": {

"collapsed": 'true'

},

"source": [

"# 3. Наследование\n",

"Наследование – важная составляющая объектно-ориентированного программирования. Так или иначе мы уже сталкивались с ним, ведь объекты наследуют атрибуты своих классов. Однако обычно под наследованием в ООП понимается наличие классов и подклассов. Также их называют супер- или надклассами и классами, а также родительскими и дочерними классами.\n",

"\n",

"Суть наследования здесь схожа с наследованием объектами от классов. Дочерние классы наследуют атрибуты родительских, а также могут переопредять атрибуты и добавлять свои."

]

},

{

"cell_type": "markdown",

"metadata": {

"collapsed": 'true'

},

"source": [

"# 3.1. Простое наследование"

]

},

{

"cell_type": "code",

"execution_count": 14,

"metadata": {

"collapsed": 'true'

},

"outputs": [],

"source": [

"class Table:\n",

" def __init__(self, l, w, h):\n",

" self.lenght = l\n",

" self.width = w\n",

" self.height = h\n",

" \n",

"class KitchenTable(Table):\n",

" def setPlaces(self, p):\n",

" self.places = p\n",

" \n",

"class DeskTable(Table):\n",

" def square(self):\n",

" return self.width * self.lenght"

]

},

{

"cell_type": "markdown",

"metadata": {

"collapsed": 'true'

},

"source": [

"В данном случае классы KitchenTable и DeskTable не имеют своих собственных конструкторов, поэтому наследуют его от родительского класса. При создании экземпляров этих столов, передавать аргументы для __init__() обязательно, иначе возникнет ошибка:"

]

},

{

"cell_type": "code",

"execution_count": 15,

"metadata": {},

"outputs": [

{

"ename": "TypeError",

"evalue": "__init__() missing 3 required positional arguments: 'l', 'w', and 'h'",

"output_type": "error",

"traceback": [

"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",

"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",

"\u001b[1;32m
1   2   3   4


написать администратору сайта