\# Отчёт по Теме 9 Соловьёва Екатерина. А-01-23 \## 1. Запуск интерактивной оболочки IDLE. \## 2. Создание классов и их наследников \## 2.1. Создание автономного класса Класс с именем Class1, содержащий 2 функции: ```py class Class1: #Объявление класса   def zad\_zn(self,znach): #Метод 1 класса1 – задание значения data   self.data=znach # self - ссылка на экземпляр класса   def otobrazh(self): # Метод 2 класса1   print(self.data)#Отображение данных экземпляра класса   z1=Class1() #Создаём 1-й экземпляр класса z2=Class1() #Создаём 2-й экземпляр класса z1.zad\_zn('экз.класса 1') #Обращение к методу класса у 1-го экз. z1 <\_\_main\_\_.Class1 object at 0x00000244872A6660> z2.zad\_zn(-632.453) #Обращение к методу класса у 2-го экз. z2 <\_\_main\_\_.Class1 object at 0x0000024487293C50> z1.otobrazh() экз.класса 1 z2.otobrazh() -632.453 z1.data='Новое значение атрибута у экз.1' # Измените значение атрибута у первого экземпляра z1.otobrazh() Новое значение атрибута у экз.1 ``` \## 2.2. Создание класса-наследника В объявлении класса после его имени в скобках перечисляются его «родительские классы» ```py class Class2(Class1): #Class2 - наследник класса Class1   def otobrazh(self): # Метод класса Class2 – переопределяет метод родителя   print('значение=',self.data)#Отображение данных экземпляра z3=Class2() dir(z3) \['\_\_class\_\_', '\_\_delattr\_\_', '\_\_dict\_\_', '\_\_dir\_\_', '\_\_doc\_\_', '\_\_eq\_\_', '\_\_firstlineno\_\_', '\_\_format\_\_', '\_\_ge\_\_', '\_\_getattribute\_\_', '\_\_getstate\_\_', '\_\_gt\_\_', '\_\_hash\_\_', '\_\_init\_\_', '\_\_init\_subclass\_\_', '\_\_le\_\_', '\_\_lt\_\_', '\_\_module\_\_', '\_\_ne\_\_', '\_\_new\_\_', '\_\_reduce\_\_', '\_\_reduce\_ex\_\_', '\_\_repr\_\_', '\_\_setattr\_\_', '\_\_sizeof\_\_', '\_\_static\_attributes\_\_', '\_\_str\_\_', '\_\_subclasshook\_\_', '\_\_weakref\_\_', 'otobrazh', 'zad\_zn'] z3.zad\_zn('Совсем новое') z3.otobrazh() значение= Совсем новое z1.otobrazh() Новое значение атрибута у экз.1 del z1,z2,z3 ``` Объекты класса Class2 всегда используют переопределенные методы из Class2, даже если идентичные методы существуют в родительском классе Class1 \## 3. Использование классов, содержащихся в модулях Модуль с именем Mod3: ```py class Class1: #Объявление класса Class1 в модуле   def zad\_zn(self,znach): # 1 Метод класса   self.data=znach # self - ссылка на экземпляр класса Class1   def otobrazh(self): # 2 Метод класса   print(self.data)#Отображение данных экземпляра class Class2(Class1): #Class2 - наследник класса Class1   def otobrazh(self): # Метод класса Class2   print('значение=',self.data)#Отображение данных экземпляра def otobrazh(objekt): #Объявление самостоятельной функции   print('значение объекта=',objekt) ``` ```py from Mod3 import Class1 z4=Class1() z4.otobrazh() Traceback (most recent call last):   File "", line 1, in   z4.otobrazh()   File "C:\\Users/Ekaterina/OneDrive/Desktop/Solovyova/python-labs/TEMA9\\Mod3.py", line 5, in otobrazh   print(self.data)#Отображение данных экземпляра AttributeError: 'Class1' object has no attribute 'data' ``` Ошибка возникла потому, что метод otobrazh() был вызван до того, как был вызван метод zad\_zn(), который создает атрибут data. ```py from Mod3 import Class1 z4=Class1() z4.data='значение данного data у экз.4' z4.otobrazh() значение данного data у экз.4 del z4 import Mod3 z4=Mod3.Class2() z4.zad\_zn('Класс из модуля') z4.otobrazh() значение= Класс из модуля Mod3.otobrazh('Объект') значение объекта= Объект ``` Результаты различаются потому, что в первом случае использовался метод из Class1, а во втором - переопределенный метод из Class2 плюс самостоятельная функция с таким же именем \## 4. Использование специальных методов Имена специальных методов предваряются одним или двумя подчерками и имеют вид: \_\_<имя специального метода>\_\_ Для примера создам класс, содержащий два специальных метода   class Class3(Class2): #Наследник класса Class2, а через него – и класса Class1   def \_\_init\_\_(self,znach): #Конструктор-вызывается при создании нового экземпляра клас-са   self.data=znach   def \_\_add\_\_(self,drug\_zn): #Вызывается, когда экземпляр участвует в операции «+»   return Class3(self.data+drug\_zn)   def zad\_dr\_zn(self,povtor): #А это - обычный метод   self.data\*=povtor Метод \_\_add\_\_ - это один из методов, осуществляющих так называемую «перегрузку» операторов. Для иллюстрации работы этих методов создам экземпляр класса Class3 ```py z5=Class3('abc') z5.otobrazh() значение= abc z6=z5+'def' z6.otobrazh() значение= abcdef z6.zad\_dr\_zn(3) z6.otobrazh() значение= abcdefabcdefabcdef ``` \## 5. Присоединение атрибутов к классу. ```py dir(Class3) \['\_\_add\_\_', '\_\_class\_\_', '\_\_delattr\_\_', '\_\_dict\_\_', '\_\_dir\_\_', '\_\_doc\_\_', '\_\_eq\_\_', '\_\_firstlineno\_\_', '\_\_format\_\_', '\_\_ge\_\_', '\_\_getattribute\_\_', '\_\_getstate\_\_', '\_\_gt\_\_', '\_\_hash\_\_', '\_\_init\_\_', '\_\_init\_subclass\_\_', '\_\_le\_\_', '\_\_lt\_\_', '\_\_module\_\_', '\_\_ne\_\_', '\_\_new\_\_', '\_\_reduce\_\_', '\_\_reduce\_ex\_\_', '\_\_repr\_\_', '\_\_setattr\_\_', '\_\_sizeof\_\_', '\_\_static\_attributes\_\_', '\_\_str\_\_', '\_\_subclasshook\_\_', '\_\_weakref\_\_', 'otobrazh', 'zad\_dr\_zn', 'zad\_zn'] Class3.fio='Иванов И.И.' dir(Class3) \['\_\_add\_\_', '\_\_class\_\_', '\_\_delattr\_\_', '\_\_dict\_\_', '\_\_dir\_\_', '\_\_doc\_\_', '\_\_eq\_\_', '\_\_firstlineno\_\_', '\_\_format\_\_', '\_\_ge\_\_', '\_\_getattribute\_\_', '\_\_getstate\_\_', '\_\_gt\_\_', '\_\_hash\_\_', '\_\_init\_\_', '\_\_init\_subclass\_\_', '\_\_le\_\_', '\_\_lt\_\_', '\_\_module\_\_', '\_\_ne\_\_', '\_\_new\_\_', '\_\_reduce\_\_', '\_\_reduce\_ex\_\_', '\_\_repr\_\_', '\_\_setattr\_\_', '\_\_sizeof\_\_', '\_\_static\_attributes\_\_', '\_\_str\_\_', '\_\_subclasshook\_\_', '\_\_weakref\_\_', 'fio', 'otobrazh', 'zad\_dr\_zn', 'zad\_zn'] z7=Class3(123) dir(z7)==dir(Class3) False dir(z7) \['\_\_add\_\_', '\_\_class\_\_', '\_\_delattr\_\_', '\_\_dict\_\_', '\_\_dir\_\_', '\_\_doc\_\_', '\_\_eq\_\_', '\_\_firstlineno\_\_', '\_\_format\_\_', '\_\_ge\_\_', '\_\_getattribute\_\_', '\_\_getstate\_\_', '\_\_gt\_\_', '\_\_hash\_\_', '\_\_init\_\_', '\_\_init\_subclass\_\_', '\_\_le\_\_', '\_\_lt\_\_', '\_\_module\_\_', '\_\_ne\_\_', '\_\_new\_\_', '\_\_reduce\_\_', '\_\_reduce\_ex\_\_', '\_\_repr\_\_', '\_\_setattr\_\_', '\_\_sizeof\_\_', '\_\_static\_attributes\_\_', '\_\_str\_\_', '\_\_subclasshook\_\_', '\_\_weakref\_\_', 'data', 'fio', 'otobrazh', 'zad\_dr\_zn', 'zad\_zn'] dir(Class3) \['\_\_add\_\_', '\_\_class\_\_', '\_\_delattr\_\_', '\_\_dict\_\_', '\_\_dir\_\_', '\_\_doc\_\_', '\_\_eq\_\_', '\_\_firstlineno\_\_', '\_\_format\_\_', '\_\_ge\_\_', '\_\_getattribute\_\_', '\_\_getstate\_\_', '\_\_gt\_\_', '\_\_hash\_\_', '\_\_init\_\_', '\_\_init\_subclass\_\_', '\_\_le\_\_', '\_\_lt\_\_', '\_\_module\_\_', '\_\_ne\_\_', '\_\_new\_\_', '\_\_reduce\_\_', '\_\_reduce\_ex\_\_', '\_\_repr\_\_', '\_\_setattr\_\_', '\_\_sizeof\_\_', '\_\_static\_attributes\_\_', '\_\_str\_\_', '\_\_subclasshook\_\_', '\_\_weakref\_\_', 'fio', 'otobrazh', 'zad\_dr\_zn', 'zad\_zn'] ``` \## 6. Выявление родительских классов Такое выявление делается с помощью специального атрибута \_\_bases\_\_, например, выведите родительский класс для созданного класса Class3:   Class3.\_\_bases\_\_ Или для класса Class2:   Class2.\_\_bases\_\_ Самостоятельно проверьте, какой родительский класс у класса Class1. Для получения всей цепочки наследования используйте атрибут \_\_mro\_\_:   Class3.\_\_mro\_\_ Например, получите всю цепочку наследования для встроенного класса ошибок «деление на ноль»:   ZeroDivisionError.\_\_mro\_\_ \## 7. Создание свойства класса. Свойство (property) класса – это особый атрибут класса, с которым можно производить операции чтения или задания его значения, а также удаление значения этого атрибута. Создайте, например, новый класс с определенным в нем свойством  class Class4:   def \_\_init\_\_(sam,znach):   sam.\_\_prm=znach   def chten(sam):   return sam.\_\_prm   def zapis(sam,znch):   sam.\_\_prm=znch   def stiran(sam):   del sam.\_\_prm   svojstvo=property(chten,zapis,stiran) Обратите внимание на то, что здесь имеется 3 метода: chten, zapis, stiran, которые обслуживают созданное свойство, реализуя операции, соответственно, чтения, записи или удаления значений свойства. Теперь попробуйте некоторые операции с этим свойством   exempl=Class4(12)   exempl.svojstvo   exempl.svojstvo=45   print(exempl.svojstvo)   del exempl.svojstvo После этого попробуйте еще раз отобразить значение свойства.   exempl.svojstvo Объясните полученный результат. \## 8. Рассмотрите пример представления в виде класса модели системы автоматического регулиро-вания (САР), состоящей из последовательного соединения усилителя и двух инерционных звень-ев, охваченных отрицательной обратной связью с усилителем. Создайте модуль SAU.py с классом: class SAU:   def \_\_init\_\_(self,zn\_param):   self.param=zn\_param   self.ypr=\[0,0]   def zdn\_zn(self,upr):   self.x=upr     def model(self):   def inerz(x,T,yy):   return (x+T\*yy)/(T+1)   y0=self.x-self.ypr\[1]\*self.param\[3] #Обр.связь с усилителем 2   y1=self.param\[0]\*y0 #Усилитель1   y2=inerz(y1,self.param\[1],self.ypr\[0]) #Инерционное звено1   y3=inerz(y2,self.param\[2],self.ypr\[1]) #Инерционное звено2   self.ypr\[0]=y2   self.ypr\[1]=y3   def otobraz(self):   print('y=',self.ypr\[1]) Тестирование класса произведите с помощью следующей программы: \###main\_SAU prm=\[2.5,4,1.3,0.8] #Параметры модели: коэф.усиления, 2 пост.времени, обратная связь from SAU import \* xx=\[0]+\[1]\*20 #Входной сигнал – «ступенька» SAUe=SAU(prm) # Создаём экземпляр класса yt=\[] for xt in xx: # Прохождение входного сигнала   SAUe.zdn\_zn(xt)   SAUe.model()   SAUe.otobraz()   yt.append(SAUe.ypr\[1]) import pylab pylab.plot(yt) pylab.show() Запустите программу на выполнение и изучите вид выходного сигнала при разных значениях параметров САР. \## 9. Сохраните созданный текстовый файл протокола в своем рабочем каталоге. Закончите се-анс работы с IDLE.