# Отчет по теме 7 "Создание пользовательских функций"  

***Цель работы: получение навыков создания пользовательских функций для использования в программах на Python.***  

Терехов Фёдор Валерьевич, А-01-23  


>Пользовательская функция – это совокупность инструкций, которая выполняется при обращении к функции из любого места программы. Как и при использовании других языков программирования, в виде функции оформляются инструкции, которые могут многократно потребоваться при выполнении данной программы или могут быть использованы в других программах. Аргументы функции – это ссылки на объекты-источники данных, которые используются при её выполнении. Возвращаемые данные – это результаты вычисления функции, передаваемые в ту часть программы, из которой была вызвана функция. Функция является объектом класса function.  


## 1. Создание пользовательской функции.  

>*Создание функции предполагает выполнение трех операций: формирование функции, ее сохранение и использование.*  

**В общем виде функция в языке Python представляется так:**  
```python
def  <Имя функции>([<Список аргументов >]):
[<отступы>″″″<Комментарий по назначению функции>″″″]
<отступы><Блок инструкций – тело функции>
[<отступы>return <Значение или вычисляемое выражение>]
```

>Именование функций должно производиться по тем же правилам задания имен: совокупность латинских букв, цифр, знаков подчеркивания. Имя должно начинаться с буквы или знака подчеркивания и не должно совпадать с зарезервированными идентификаторами или ключевыми словами, а также не должно содержать пробелов. Желательно использовать мнемонические имена, отражающие назначение функции. Функция считается оконченной, если в очередной строке нет отступов или их число меньше, чем в отступах в функции. Если при выполнении функции будет выполнена инструкция return, то выполнение функции прекращается с возвратом значения, следующего за этой инструкцией. Однако наличие этой инструкции в функции является необязательным.  
Если в Блоке инструкций только одна инструкция, её можно записывать без отступов сразу за знаком «:».  

Пример 1.1:  

**Первый пример: функция – без аргументов.**  

```python
def uspeh():
	"""Подтверждение успеха операции"""
	print('Выполнено успешно!')
uspeh()
print("Класс объекта uspeh:", type(uspeh))
print("Пространство имен:", dir())
```

Ответ программы:  
```shell
Выполнено успешно!
Класс объекта uspeh: <class 'function'>
Пространство имен: ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'uspeh']
```

```python
help(uspeh)
```

Ответ программы:  
```shell
Help on function uspeh in module __main__:

uspeh()
    Подтверждение успеха операции
```

Пример 1.2:  

**Пример функции с аргументами.**  

```python
def sravnenie(a,b):
	"""Сравнение a и b"""
	if a>b:
		print(a,' больше ',b)
	elif a<b:
		print(a, ' меньше ',b)
	else:
		print(a, ' равно ',b)
n,m=16,5; sravnenie(n,m)
```

Ответ программы:  
```shell
16  больше  5
```

```python
def sravnenie(a,b):
	"""Сравнение a и b"""
	if a>b:
		print(a,' больше ',b)
	elif a<b:
		print(a, ' меньше ',b)
	else:
		print(a, ' равно ',b)
n,m="wsd","wd"; sravnenie(n,m)
```

Ответ программы:  
```shell
wsd  больше  wd
```

*Объяснение поведения программы:*  
*Сравниваются строки "wsd" и "wd". Строки сравниваются лексикографически (посимвольно). Первые символы 'w' и 'w' равны. Вторые символы 's' и 'd' - 's' имеет больший код, чем 'd'. Поэтому "wsd" > "wd". Выполняется условие a > b и выводится "wsd больше wd".*  

Пример 1.3:  

**Пример функции, содержащей return.**  

```python
def logistfun(b,a):
	"""Вычисление логистической функции"""
	import math
	return a/(1+math.exp(-b))

v,w=1,0.7; z=logistfun(w,v)
print(z)
```

Ответ программы:  
```shell
0.6681877721681662
```

Пример 1.4:  

**Сложение для разных типов аргументов.**  

```python
def slozh(a1,a2,a3,a4):
	""" Сложение значений четырех аргументов"""
	return a1+a2+a3+a4
print(slozh(1,2,3,4))   # Сложение чисел
print(slozh('1','2','3','4'))  # Сложение строк
b1=[1,2];b2=[-1,-2];b3=[0,2];b4=[-1,-1]
q=slozh(b1,b2,b3,b4)  #Сложение списков
print(q)
tuple1=(1,2);tuple2=(-1,-2);tuple3=(0,2);tuple4=(-1,-1)
print(slozh(tuple1,tuple2,tuple3,tuple4))
dict1={'a':1,'b':2};dict2={'a':-1,'b':-2};dict3={'a':0,'b':2};dict4={'a':-1,'b':-1}
print(slozh(dict1,dict2,dict3,dict4))
```

Ответ программы:  
```shell
10
1234
[1, 2, -1, -2, 0, 2, -1, -1]
(1, 2, -1, -2, 0, 2, -1, -1)
Traceback (most recent call last):
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task1.4.py", line 12, in <module>
    print(slozh(dict1,dict2,dict3,dict4))
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task1.4.py", line 3, in slozh
    return a1+a2+a3+a4
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
```

*В Python словари напрямую не поддерживают операции сложения.*  

Пример 1.5:  

**Функция, реализующая модель некоторого устройства, на вход которого в текущий момент поступает сигнал х, на выходе получается сигнал y.**  

```python
import matplotlib.pyplot as plt

def inerz(x, T, ypred):
    """Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы"""
    y = (x + T * ypred) / (T + 1)
    return y

sps = [0] + [1] * 100  # Список с измерениями значений входного сигнала
spsy = []  # Заготовка для значений выхода
TT = 20  # Постоянная времени
yy = 0  # Нулевое начальное условие

for xx in sps:
    yy = inerz(xx, TT, yy)
    spsy.append(yy)

# Построение графика
plt.plot(sps, spsy)
plt.xlabel('Входное значение')
plt.ylabel('Выходное значение')
plt.title('График выходного сигнала')
plt.show()
```

Ответ программы:  
![График ступенька](images/Figure_1.5.png)

## 2. Функции как объекты.  

### 2.1. Получение списка атрибутов объекта-функции.  

```python
def inerz(x, T, ypred):
    """Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы"""
    y = (x + T * ypred) / (T + 1)
    return y

sps = [0] + [1] * 100  # Список с измерениями значений входного сигнала
spsy = []  # Заготовка для значений выхода
TT = 20  # Постоянная времени
yy = 0  # Нулевое начальное условие

for xx in sps:
    yy = inerz(xx, TT, yy)
    spsy.append(yy)

print(dir(inerz))
```

Ответ программы:  
```shell
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
```

```python
def inerz(x, T, ypred):
    """Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы"""
    y = (x + T * ypred) / (T + 1)
    return y

sps = [0] + [1] * 100  # Список с измерениями значений входного сигнала
spsy = []  # Заготовка для значений выхода
TT = 20  # Постоянная времени
yy = 0  # Нулевое начальное условие

for xx in sps:
    yy = inerz(xx, TT, yy)
    spsy.append(yy)


print(inerz.__doc__)
```

Ответ программы:  
```shell
Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы
```

```python
def inerz(x, T, ypred):
    """Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы"""
    y = (x + T * ypred) / (T + 1)
    return y

sps = [0] + [1] * 100  # Список с измерениями значений входного сигнала
spsy = []  # Заготовка для значений выхода
TT = 20  # Постоянная времени
yy = 0  # Нулевое начальное условие

for xx in sps:
    yy = inerz(xx, TT, yy)
    spsy.append(yy)


print(inerz.__doc__)
help(inerz)
```

Ответ программы:  
```shell
Help on function inerz in module __main__:

inerz(x, T, ypred)
    Модель устройства с памятью:
    x - текущее значение входного сигнала,
    T - постоянная времени,
    ypred - предыдущее значение выхода системы
```

*Информация взята из описания функции в тройных кавычках.*  


### 2.2. Сохранение ссылки на объект-функцию в другой переменной.  

```python
def sravnenie(a,b):
	"""Сравнение a и b"""
	if a>b:
		print(a,' больше ',b)
	elif a<b:
		print(a, ' меньше ',b)
	else:
		print(a, ' равно ',b)
fnkt=sravnenie
v=16
fnkt(v,23)
```

Ответ программы:  
```shell
16  меньше  23
```

### 2.3.  Возможность альтернативного определения функции в программе.  

```python
typ_fun=8
if typ_fun==1:
	def func():
		print('Функция 1')
else:
	def func():
		print('Функция 2')

func()
```

Ответ программы (1 попытка):  
```shell
Функция 2
```

>В данном случае, функция func() определяется в зависимости от значения переменной typ_fun. Если typ_fun равно 1, то будет определена функция func(), которая выводит сообщение "Функция 1". Если typ_fun не равно 1, то будет определена функция func(), которая выводит сообщение "Функция 2".  

## 3. Аргументы функции.  

### 3.1. Возможность использования функции в качестве аргумента другой функции.  

```python
def logistfun(b,a):
	"""Вычисление логистической функции"""
	import math
	return a/(1+math.exp(-b))
def fun_arg(fff,a,b,c):
	"""fff-имя функции, используемой 
	в качестве аргумента функции fun_arg"""
	return a+fff(c,b)

zz=fun_arg(logistfun,-3,1,0.7)
print(zz)
```

Ответ программы:  
```shell
-2.3318122278318336
```

### 3.2. Обязательные и необязательные аргументы.  

```python
def logistfun(a,b=1):   #Аргумент b – необязательный; значение по умолчанию=1
	"""Вычисление логистической функции"""
	import math
	return b/(1+math.exp(-a))

print(logistfun(0.7))     #Вычисление со значением b по умолчанию
print(logistfun(0.7,2))  #Вычисление с заданным значением b
```

Ответ программы:  
```shell
0.6681877721681662
1.3363755443363323
```

### 3.3. Возможность обращения к функции с произвольным (непозиционным) расположением аргументов. При этом надо в обращении к функции указывать имена аргументов.  

```python
def logistfun(a,b=1):
	"""Вычисление логистической функции"""
	import math
	return b/(1+math.exp(-a))

print(logistfun(b=0.5,a=0.8)) # Ссылки на аргументы поменялись местами
```

Ответ программы:  
```shell
0.34498724056380625
```

### 3.4. Пример со значениями аргументов функции, содержащимися в списке или кортеже.  

```python
def slozh(a1,a2,a3,a4):
	""" Сложение значений четырех аргументов"""
	return a1+a2+a3+a4
b1=[1,2];b2=[-1,-2];b3=[0,2];b4=[-1,-1]
b1234=[b1,b2,b3,b4]  # Список списков из п.2.4
qq=slozh(*b1234)  #Перед ссылкой на список или кортеж надо ставить звездочку
print(qq)
```

Ответ программы:  
```shell
[1, 2, -1, -2, 0, 2, -1, -1]
```

### 3.5. Пример со значениями аргументов функции, содержащимися в словаре.  

```python
def slozh(a1,a2,a3,a4):
	""" Сложение значений четырех аргументов"""
	return a1+a2+a3+a4
dic4={"a1":1,"a2":2,"a3":3,"a4":4}
qq=slozh(**dic4)  #Перед ссылкой на словарь надо ставить две звездочки
print(qq)
```

Ответ программы:  
```shell
10
```

### 3.6. Смешанные ссылки.  

```python
def slozh(a1,a2,a3,a4):
	""" Сложение значений четырех аргументов"""
	return a1+a2+a3+a4
e1=(-1,6);dd2={'a3':3,'a4':9}
qq=slozh(*e1,**dd2)
print(qq)
```

Ответ программы:  
```shell
17
```

### 3.7. Переменное число аргументов у функции.  

```python
def func4(*kort7):
	"""Произвольное число аргументов в составе кортежа"""
	smm=0
	for elt in kort7:
		smm+=elt
	return smm

print(func4(-1,2))  #Обращение к функции с 2 аргументами
print(func4(-1,2,0,3,6))  #Обращение к функции с 5 аргументами
```

Ответ программы:  
```shell
1
10
```

### 3.8. Комбинация аргументов.  

```python
def func4(a,b=7,*kort7): #Аргументы: a-позиционный, b- по умолчанию + кортеж
	"""Кортеж - сборка аргументов - должен быть последним!"""
	smm=0
	for elt in kort7:
		smm+=elt
	return a*smm+b
print(func4(-1,2,0,3,6))
```

Ответ программы:  
```shell
-7
```

### 3.9. Изменение значений объектов, используемых в качестве аргументов функции.  

***Такое изменение возможно только у объектов изменяемого типа.***  

**Пример с числовым объектом.**  

```python
a=90    # Числовой объект – не изменяемый тип
def func3(b):
    b=5*b+67
func3(a)
print(a)
```

Ответ программы:  
```shell
90
```

>Значение переменной a не изменилось. В данном коде, функция func3(b) принимает аргумент b и выполняет вычисления над ним. Изменения, внесенные в переменную b внутри функции, не влияют на значение переменной a вне функции. Значение переменной a остается неизменным со значением 90.  

**Пример со списком.**  

```python
sps1=[1,2,3,4]  #Список – изменяемый тип объекта
def func2(sps):
    sps[1]=99
func2(sps1)
print(sps1)
```

Ответ программы:  
```shell
[1, 99, 3, 4]
```

>Когда мы вызываем функцию func2(sps1), мы передаем список sps1 в качестве аргумента. Внутри функции, мы меняем значение элемента списка sps с индексом 1, что влечет за собой изменение значения элемента в списке sps1.  

**Пример с кортежом.**  

```python
kort=(1,2,3,4)   #Кортеж – неизменяемый тип объекта
def func2(sps):
    sps[1]=99
func2(kort)
print(kort)
```

Ответ программы:  
```shell
Traceback (most recent call last):
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task3.9.3.py", line 4, in <module>
    func2(kort)
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task3.9.3.py", line 3, in func2
    sps[1]=99
TypeError: 'tuple' object does not support item assignment
```

>Причина этой ошибки заключается в том, что кортеж (kort) является неизменяемым типом объекта, и поэтому мы не можем изменять его элементы.  

## 4. Специальные типы пользовательских функций.  

### 4.1. Анонимные функции.  

*Анонимные функции или по-другому их называют лямбда-функциями – это функции без имени (поэтому их и называют анонимными), определяемые по следующей схеме:*  

***Общее правило написания:***  
lambda [<Аргумент1>[,<Аргумент2>,…]]:<Возвращаемое значение или выражение>  

*Анонимная функция возвращает ссылку на объект-функцию, которую можно присвоить другому объекту.*  

```python
import math
anfun1=lambda: 1.5+math.log10(17.23)  #Анонимная функция без аргументов
print(anfun1())   # Обращение к объекту-функции
anfun2=lambda a,b : a+math.log10(b)  #Анонимная функция с 2 аргументами
print(anfun2(17,234))
anfun3=lambda a,b=234: a+math.log10(b) #Функция с необязательным вторым аргументом
print(anfun3(100))
```

Ответ программы:  
```shell
2.7362852774480286
19.369215857410143
102.36921585741014
```

### 4.2. Функции-генераторы.  

*Это – такие функции, которые используются в итерационных процессах, позволяя на каждой итерации получать одно из значений. Для этого в функцию включают инструкцию yield приостанавливающую её выполнение и возвращающую очередное значение.*  

```python
def func5(diap,shag):
    """ Итератор, возвращающий значения
    ​из диапазона от 1 до diap с шагом shag"""
    for j in range(1,diap+1,shag):
     yield j

for mm in func5(7,3):
  print(mm)
```

Ответ программы:  
```shell
1
4
7
```

>Здесь при каждом обращении к функции будет генерироваться только одно очередное значение.  

*При программировании задач у таких функций часто используют метод __next__, активирующий очередную итерацию выполнения функции.*  

```python
def func5(diap,shag):
    """ Итератор, возвращающий значения
    ​из диапазона от 1 до diap с шагом shag"""
    for j in range(1,diap+1,shag):
     yield j

alp=func5(7,3)
print(alp.__next__())
print(alp.__next__())
print(alp.__next__())
```

Ответ программы:  
```shell
1
4
7
```

Если попытаться выполнить ещё раз инструкцию print(alp.__next__()), выведется ошибка:  
```shell
1
4
7
Traceback (most recent call last):
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task4.2.py", line 11, in <module>
    print(alp.__next__())
StopIteration
```

*После получения значений 1, 4 и 7, вызов alp.__next__() возвращает ошибку StopIteration, потому что все значения из итератора уже получены.*  

## 5. Локализация объектов в функциях.  

>По отношению к функции все объекты подразделяются на локальные и глобальные. Локальными являются объекты, которые создаются в функциях присваиванием им некоторых значений. Они записываются в пространство имен, создаваемое в функции.  Глобальные – это те объекты, значения которых заданы вне функции. Они определены в пространствах имен вне функции.
Локализация может быть переопределена путем прямого объявления объектов как глобальных с помощью дескриптора global.  

### 5.1. Примеры на локализацию объектов.  

***Одноименные локальный и глобальный объекты.***  

```python
glb=10
def func7(arg):
    loc1=15
    glb=8
    return loc1*arg
 
res=func7(glb)
print(res)
```

Ответ программы:  
```shell
150
```

* *Объект glb является глобальной переменной и используется внутри функции func7(arg). Внутри функции, значение переменной glb изменяется на 8. Однако, изменение значения глобальной переменной внутри функции не влияет на ее значение вне функции.*
* *Объект arg передается в качестве аргумента функции func7(arg) и используется внутри функции для вычисления результата. Значение arg остается неизменным вне функции.*  

***Ошибка в использовании локального объекта.***  

```python
glb=10
def func8(arg):
   loc1=15
   print(glb)
   glb=8
   return loc1*arg
 
res=func8(glb)
print(res)
```

Ответ программы:  
```shell
Traceback (most recent call last):
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task6.1.2.py", line 8, in <module>
    res=func8(glb)
  File "/Users/fedorterekhov/Library/Mobile Documents/com~apple~CloudDocs/Учёба/3 курс/POAS_labs/python-labs/TEMA7/task6.1.2.py", line 4, in func8
    print(glb)
UnboundLocalError: local variable 'glb' referenced before assignment
```

>Ошибка UnboundLocalError возникает, когда переменная, используемая внутри функции, не была объявлена в области видимости функции или не была присвоена до использования. Переменная glb объявлена как глобальная переменная, но внутри функции func8(arg) она используется до того, как ей будет присвоено новое значение. Это вызывает ошибку UnboundLocalError, так как переменная glb не была объявлена в области видимости функции.  

***Переопределение локализации объекта.***  

```python
glb=11
def func7(arg):
  loc1=15
  global glb
  print(glb)
  glb=8
  return loc1*arg

res=func7(glb)
print(res)
print(glb)
```

Ответ программы:  
```shell
11
165
8
```

### 5.2. Выявление локализации объекта с помощью функций locals() и globals() из builtins.  

>Эти функции возвращают словари, ключами в которых будут имена объектов, являющихся, соответственно, локальными или глобальными на уровне вызова этих функций.  

```python
glb=11
def func7(arg):
  loc1=15
  global glb
  print(glb)
  glb=8
  return loc1*arg

res=func7(glb)
print(globals().keys())  #Перечень глобальных объектов
print(locals().keys())  #Перечень локальных объектов
```

Ответ программы:  
```shell
11
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'glb', 'func7', 'res'])
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'glb', 'func7', 'res'])
```

*В этих перечнях нет различий, тк locals().keys() возвращает список имен локальных объектов. Это означает, что это список имен всех переменных, функций и других объектов, определенных в текущей функции или блока кода. В данном коде locals().keys() записана в основной блок кода. Поэтому перечни совпадают.*  

```python
glb=11
def func8(arg):
  loc1=15
  glb=8
  print(globals().keys())  #Перечень глобальных объектов
  print(locals().keys())  #Перечень локальных объектов
  return loc1*arg

res=func8(glb)
print('glb' in globals().keys())
```

Ответ программы:  
```shell
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'glb', 'func8'])
dict_keys(['arg', 'loc1', 'glb'])
True
```

* *globals().keys() возвращает список имен глобальных объектов. Это означает, что это список имен всех глобальных переменных, функций, модулей и других объектов, доступных в текущем контексте.*
* *locals().keys() возвращает список имен локальных объектов. Это означает, что это список имен всех переменных, функций и других объектов, определенных в текущей функции или блока кода.*  

### 5.3. Локализация объектов при использовании вложенных функций.  

```python
def func9(arg2,arg3):
  def func9_1(arg1):
    loc1=15
    glb1=8
    print('glob_func9_1:',globals().keys())
    print('locl_func9_1:',locals().keys())
    return loc1*arg1
  loc1=5
  glb=func9_1(loc1)
  print('loc_func9:',locals().keys())
  print('glob_func9:',globals().keys())
  return arg2+arg3*glb
 
kk=func9(10,1)
print(kk)
```

Ответ программы:  
```shell
glob_func9_1: dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'func9'])
locl_func9_1: dict_keys(['arg1', 'loc1', 'glb1'])
loc_func9: dict_keys(['arg2', 'arg3', 'func9_1', 'loc1', 'glb'])
glob_func9: dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'func9'])
85
```

*Анализируя вывод на экран, мы можем увидеть, что:*  

* *Внутри функции func9_1(arg1), переменная loc1 и глобальная переменная glb1 объявляются и используются. Вывод locals().keys() внутри func9_1(arg1) показывает, что arg1, loc1 и glb1 являются локальными объектами.*
* *Внутри функции func9(arg2, arg3), переменная loc1 и глобальная переменная glb объявляются и используются. Вывод locals().keys() внутри func9(arg2, arg3) показывает, что arg2, arg3, glb и loc1 являются локальными объектами.*
* *В глобальном контексте, функции func9(arg2, arg3) и func9_1(arg1) являются глобальными объектами. Вывод globals().keys() внутри func9_1(arg1) и func9(arg2, arg3) показывает, что arg2, arg3, func9 и kk являются глобальными объектами.*

### 5.4. Большой пример – моделирование системы, состоящей из последовательного соединения реального двигателя, охваченного отрицательной обратной связью с тахогенератором в ней, и нелинейного звена типа «зона нечувствительности», при подаче на неё синусоидального входного сигнала.  

>Реальный двигатель: последовательное соединение усилителя с коэффициентом усиления k1,интегратора: y(t)=x(t)+y(t-1), и инерционного звена: y(t)=(x(t)+T*y(t-1)) / (T+1) с постоянной времени Т.
Тахогенератор: последовательное соединение усилителя с коэффициентом усиления k2 и интегратора: y(t)=x(t)+y(t-1).
Нелинейное звено типа «зона нечувствительности»: y=0 при -xm≤ x ≤xm, y=x-xm при x>xm, y=x+xm при x<-xm.
Таким образом, система характеризуется параметрами: k1, T, k2, xm. Входной сигнал характеризуется параметрами: A (амплитуда синусоиды) и F (период синусоиды).
Еще один параметр задачи : N – время (число тактов) подачи сигнала.  

```python
import math

znach=input('k1,T,k2,Xm,A,F,N=').split(',')
k1 = float(znach[0])
T = float(znach[1])
k2 = float(znach[2])
Xm = float(znach[3])
A = float(znach[4])
F = float(znach[5])
N = int(znach[6])

vhod=[]
for i in range(N):
	vhod.append(A*math.sin((2*i*math.pi)/F))
        
def realdvig(xtt,kk1,TT,yti1,ytin1):
		#Модель реального двигателя
		yp=kk1*xtt  #усилитель
		yti1=yp+yti1  #Интегратор
		ytin1=(yti1+TT*ytin1)/(TT+1)
		return [yti1,ytin1]

def tahogen(xtt,kk2,yti2):
		#Модель тахогенератора
		yp=kk2*xtt   #усилитель
		yti2=yp+yti2 #интегратор
		return yti2

def nechus(xtt,gran):
#зона нечувствит
    if xtt<gran and xtt>(-gran):
        ytt=0
    elif xtt>=gran:
        ytt=xtt-gran
    elif xtt<=(-gran):
        ytt=xtt+gran
    return ytt


yi1=0;yin1=0;yi2=0
vyhod=[]
for xt in vhod:
		xt1=xt-yi2   #отрицательная обратная связь
		[yi1,yin1]=realdvig(xt1,k1,T,yi1,yin1)
		yi2=tahogen(yin1,k2,yi2)
		yt=nechus(yin1,Xm)
		vyhod.append(yt)

print('y=',vyhod)
```

Ответ программы:  
```shell
k1,T,k2,Xm,A,F,N=2.0,5.0,0.5,0.3,1.0,20.0,15     
y= [0, 0, 0.06760452541690626, 0.4793408756948438, 0.931148162040943, 1.2274710293386355, 1.1233305479712674, 0.400902344081069, -0.42732659995249095, -2.4154244800859455, -4.520514725079971, -6.022685151402792, -6.061564289571653, -3.8945172200444302, 0.16254138526353118]
```
