# Отчет по Теме 7

Турханов Артем, А-03-23

## 1 Создание пользовательской функции
```py
>>> def uspeh():
    	"""Подтверждение успеха операции"""
    	print('Выполнено успешно!')

>>> uspeh()
Выполнено успешно!
>>> type(uspeh)
<class 'function'>
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'uspeh']
>>> help(uspeh)
Help on function uspeh in module __main__:

uspeh()
    Подтверждение успеха операции
```
При вызове функции help() мы видим, что в качестве помощи по созданной нами функции uspeh отобразилось то, что мы заключили в многомерные кавычки, когда создавали нашу функцию. Отображается именно та информация, которая была записана как аннотация в многомрных кавычках. То есть можно сделать вывод: если мы хотим сообщить пользователю, который будет использовать нашу функцию, как этой функцией пользоваться, то нам необходимо всю аннотацию к функции рописать в ее "теле" во множественных кавычках.

```py
'__spec__', 'uspeh']
>>> def sravnenie(a,b):
    	"""Сравнение a и b"""
    	if a>b:
        	print(a,' больше ',b)
    	elif a<b:
        	print(a, ' меньше ',b)
    	else:
        	print(a, ' равно ',b)

'__spec__', 'uspeh']
>>> n,m=16,5;sravnenie(n,m)
16  больше  5
'__spec__', 'uspeh']
>>> n,m='16','5';sravnenie(n,m)
16  меньше  5
'__spec__', 'uspeh']
>>> n,m=16,5;sravnenie(n,m)
16  больше  5
'__spec__', 'uspeh']
>>> n,m='16','5';sravnenie(n,m)
16  меньше  5
'__spec__', 'uspeh']
>>> sravnenie('12','234')
12  меньше  234
'__spec__', 'uspeh']
>>> sravnenie('12097','234')
12097  меньше  234
'__spec__', 'uspeh']
>>> n,m='66','5';sravnenie(n,m)
66  больше  5
'__spec__', 'uspeh']
>>> n,m='66','5000';sravnenie(n,m)
66  больше  5000

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

>>> v,w=1,0.7;z=logistfun(w,v)
>>> z
0.6681877721681662

>>> def slozh(a1,a2,a3,a4):
    	""" Сложение значений четырех аргументов"""
    	return a1+a2+a3+a4

>>> slozh(1,2,3,4)   # Сложение чисел
10
>>> slozh('1','2','3','4')  # Сложение строк
'1234'
>>> b1=[1,2];b2=[-1,-2];b3=[0,2];b4=[-1,-1]
>>> q=slozh(b1,b2,b3,b4)  #Сложение списков
>>> q
[1, 2, -1, -2, 0, 2, -1, -1]
>>> slozh((1,2),(3,4),(5,6),(7,8))
(1, 2, 3, 4, 5, 6, 7, 8)
>>> slozh({'a':1, 'b':2},{'c':3, 'd':4},{'e':5, 'f':6},{'g':7, 'h':8})
     
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    slozh({'a':1, 'b':2},{'c':3, 'd':4},{'e':5, 'f':6},{'g':7, 'h':8})
  File "<pyshell#41>", line 3, in slozh
    return a1+a2+a3+a4
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

>>> slozh({1,2,3,4}, {1,2,3,4}, {5,6,7,8}, {9,10,11,12})
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    slozh({1,2,3,4}, {1,2,3,4}, {5,6,7,8}, {9,10,11,12})
  File "<pyshell#41>", line 3, in slozh
    return a1+a2+a3+a4
TypeError: unsupported operand type(s) for +: 'set' and 'set'

>>> 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)

>>> import matplotlib.pyplot as plt
>>> plt.title('Модель устройства')
Text(0.5, 1.0, 'Модель устройства')
>>> plt.xlabel('Временные отсчеты')
Text(0.5, 0, 'Временные отсчеты')
>>> plt.ylabel('Значение на выходе устройства')
Text(0, 0.5, 'Значение на выходе устройства')
>>> t = [i for i in range(len(spsy))]
     
>>> plt.plot(t, spsy)
     
[<matplotlib.lines.Line2D object at 0x0000014836B65950>]
>>> plt.show()
```
![Figure_1.png](Figure_1.png)

## 2 Функции как объекты
```py
>>> dir(inerz)
['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__getstate__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__type_params__']
>>> inerz.__doc__
'Модель устройства с памятью:\nx- текущее значение вх.сигнала,\nT -постоянная времени,\nypred - предыдущее значение выхода устройства'
>>> help(inerz)
Help on function inerz in module __main__:

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

>>> fnkt=sravnenie
>>> v=16
>>> fnkt(v,23)
16  меньше  23
```
Заметим, что функция fnkt выполняет ту же операцию, что и функция sravnenie: сравнение объектов-переменных.
```py
>>> typ_fun=8
>>> if typ_fun==1:
    	def func():
        	print('Функция 1')
	else:
    	def func():
        	print('Функция 2')

>>> func()
Функция 2
```
Вызов функции func() выдал там результат: "Функция 2". Это произошло потому, что typ_fun=8, так что typ_fun не равно 1. В связи с этим функция func() определяется конструкцией else нашего условного блока.

## 3 Аргументы функции
```py
>>> def fun_arg(fff,a,b,c):
    	"""fff-имя функции, используемой 
    	в качестве аргумента функции fun_arg"""
    	return a+fff(c,b)

>>> zz=fun_arg(logistfun,-3,1,0.7)
>>> zz
-2.3318122278318336

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

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

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

>>> b1234=[b1,b2,b3,b4]  # Список списков из п.2.4
>>> qq=slozh(*b1234)  #Перед ссылкой на список или кортеж надо ставить звездочку
>>> qq
[1, 2, -1, -2, 0, 2, -1, -1]

>>> dic4={"a1":1,"a2":2,"a3":3,"a4":4}
>>> qqq=slozh(**dic4)  #Перед ссылкой на словарь надо ставить две звездочки
>>> qqq
10
>>> e1=(-1,6);dd2={'a3':3,'a4':9}
>>> qqqq=slozh(*e1,**dd2)
>>> qqqq
17
>>> def func4(*kort7):
    	"""Произвольное число аргументов в составе кортежа"""
    	smm=0
    	for elt in kort7:
	    	smm+=elt
    	return smm

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

>>> def func44(a,b=7,**dict2):
		smm=0
		for elt in dict2.values():
			smm+=elt
		return a*smm+b

>>> d1 = {'k1':1, 'k2':2, 'k3':3}
>>> func44(1,1,**d1)
7
>>> d2 = {'k1':0, 'k2':3, 'k3':6}
>>> func44(-1,2,**d2)
-7

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

>>> func3(a)
>>> a
90

>>> sps1=[1,2,3,4]
>>> def func2(sps):
		sps[1]=99

>>> func2(sps1)
>>> print(sps1)
[1, 99, 3, 4]
>>> kort=(1,2,3,4)   #Кортеж – неизменяемый тип объекта
>>> func2(kort); kort
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    func2(kort); kort
  File "<pyshell#34>", line 2, in func2
    sps[1]=99
TypeError: 'tuple' object does not support item assignment
```
Заметим, что функция func2 изменяет только изменяемые типы. Например - списки. А числа и кортежи - это неизменяемые типы данных.

## 4 Специальные типы пользовательских функций
```py
>>> anfun1=lambda: 1.5+math.log10(17.23)  #Анонимная функция без аргументов
>>> anfun1()   # Обращение к объекту-функции
2.7362852774480286
>>> anfun2=lambda a,b : a+math.log10(b)  #Анонимная функция с 2 аргументами
>>> anfun2(17,234)
19.369215857410143
>>> anfun3=lambda a,b=234: a+math.log10(b) #Функция с необязательным вторым аргументом
>>> anfun3(100)
102.36921585741014

>>> 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)

    
1
4
7
>>> alp=func5(7,3)
>>> print(alp.__next__())
1
>>> print(alp.__next__())
4
>>> print(alp.__next__())
7
>>> print(alp.__next__())
Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    print(alp.__next__())
StopIteration
```
Так как диапазон генерации был указан до 7 включительно. А шаг был равен 3, то после трех вызовов print(alp.__next__()) мы прошлись по всему диапазону. Так что дальнейший вызов будет сопутсвоваться ошибкой.

## 5 Локализация объектов
```py
>>> glb=10
>>> def func7(arg):
    	loc1=15
    	glb=8
    	return loc1*arg

>>> res=func7(glb)
>>> res
150
>>> glb
10
```
Переменная glb, объявленная до функции, является глобальной переменной. А одноименная переменнная, объявленная в теле функции - локальной переменной, которая распространяется на пространство имен внутри функции. Поэтому глобальная одноименная переменная не поменялась после того, как функция была вызвана. При получении результата выполнения функции использовались значения локальной переменной loc1=15, объявленной в теле функции, и глобальной переменной glb=10, объявленной вне функции, но переданной последней в качестве аргумента.

```py
>>> def func8(arg):
		loc1=15
		print(glb)  
		glb=8
		return loc1*arg

    
cres=func8(glb)
Traceback (most recent call last):
  File "<pyshell#74>", line 1, in <module>
    res=func8(glb)
  File "<pyshell#73>", line 3, in func8
    print(glb)
UnboundLocalError: cannot access local variable 'glb' where it is not associated with a value
```
Ошибка возникает, потому что мы, имея глобально определенную переменную glb = 10, определяем локальную переменную с таким же именем внутри функции. Но при этом мы пытаемся вызвать print(glb) до того, как объявлена локальная переменная. Происходит конфликт: вроде есть глобальная переменная, но и локальная объявлена.

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


>>> res=func7(glb); res
11
165
```
Теперь мы объявили в теле функции переменную glb как глобальную. Поэтому, вызов print(glb) выдает значение 11. При этом, если мы потом вызывваем инструкцию glb=8, то переменная glb глобально меняет свое значение.

```py
>>> globals().keys()  #Перечень глобальных объектов
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'func4', 'func44', 'd1', 'd2', 'a', 'func3', 'func2', 'sps1', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'func5', 'mm', 'alp', 'glb', 'func7', 'res', 'func8', 'func88'])
>>> locals().keys()  #Перечень локальных объектов
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'func4', 'func44', 'd1', 'd2', 'a', 'func3', 'func2', 'sps1', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'func5', 'mm', 'alp', 'glb', 'func7', 'res', 'func8', 'func88'])
>>> globals().keys() == locals().keys()
True
```
Сейчас нет различия между перечнями, так как эти функции отображают имена локальных и глобальный переменных именно на том уровне, где они вызываются. На нашем уровне нет различий.

```py
>>> def func8(arg):
		loc1=15
		glb=8
		print(globals().keys())  #Перечень глобальных объектов «изнутри» функции
		print(locals().keys())  #Перечень локальных объектов «изнутри» функции
		return loc1*arg

    
>>> hh=func8(glb)
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'func4', 'func44', 'd1', 'd2', 'a', 'func3', 'func2', 'sps1', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'func5', 'mm', 'alp', 'glb', 'func7', 'res', 'func8', 'func88'])
dict_keys(['arg', 'loc1', 'glb'])
>>> 'glb' in globals().keys()
True
```
Внутри функции - локальные переменные: arg, loc1 и glb. Только glb - это не на glb, что объявлена вне функции. Первая - локальная, а вторая - глобальная. Поэтому имя glb встречается как в списке глобальных перемнных, так в списке локальных.
```py
>>> 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)
glob_func9_1: dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'func4', 'func44', 'd1', 'd2', 'a', 'func3', 'func2', 'sps1', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'func5', 'mm', 'alp', 'glb', 'func7', 'res', 'func8', 'func88', 'hh', '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__', 'func4', 'func44', 'd1', 'd2', 'a', 'func3', 'func2', 'sps1', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'func5', 'mm', 'alp', 'glb', 'func7', 'res', 'func8', 'func88', 'hh', 'func9'])
```

glob_func9_1 и glob_func9 одинаковые, так как для обоих функций все глобальные переменные, объявленные вне их обоих - общие. locl_func9_1 и loc_func9 отличаются. Так как locl_func9_1 - список локальных перемнных вложенной функции, а loc_func9 - внешней функции.

```py
>>> znach=input('k1,T,k2,Xm,A,F,N=').split(',')
k1,T,k2,Xm,A,F,N=100, 10, 200, 5, 1, 50, 100
>>> k1=int(znach[0]); k1
100
>>> T =int(znach[1]); T
10
>>> k2 =int(znach[2]); k2
200
>>> Xm =int(znach[3]); Xm
5
>>> A =int(znach[4]); A
1
>>> F =int(znach[5]); F
50
>>> N =int(znach[6]); N
100
>>> vhod=[]
>>> for i in range(N):
    	vhod.append(A*math.sin((2*i*math.pi)/F))

>>> vhod
[0.0, 0.12533323356430426, 0.2486898871648548, 0.3681245526846779, 0.4817536741017153, 0.5877852522924731, 0.6845471059286886, 0.7705132427757893, 0.8443279255020151, 0.9048270524660196, 0.9510565162951535, 0.9822872507286886, 0.9980267284282716, 0.9980267284282716, 0.9822872507286887, 0.9510565162951536, 0.9048270524660195, 0.844327925502015, 0.7705132427757893, 0.6845471059286888, 0.5877852522924732, 0.4817536741017152, 0.36812455268467814, 0.24868988716485524, 0.12533323356430454, 1.2246467991473532e-16, -0.12533323356430429, -0.24868988716485457, -0.3681245526846779, -0.4817536741017154, -0.5877852522924727, -0.6845471059286884, -0.7705132427757894, -0.8443279255020153, -0.9048270524660198, -0.9510565162951535, -0.9822872507286887, -0.9980267284282716, -0.9980267284282716, -0.9822872507286887, -0.9510565162951536, -0.9048270524660199, -0.844327925502015, -0.7705132427757896, -0.684547105928689, -0.5877852522924734, -0.4817536741017161, -0.36812455268467786, -0.24868988716485535, -0.12533323356430465, -2.4492935982947064e-16, 0.12533323356430418, 0.24868988716485488, 0.3681245526846782, 0.4817536741017149, 0.5877852522924729, 0.6845471059286886, 0.7705132427757887, 0.8443279255020152, 0.9048270524660194, 0.9510565162951532, 0.9822872507286886, 0.9980267284282716, 0.9980267284282716, 0.9822872507286886, 0.9510565162951536, 0.9048270524660192, 0.8443279255020151, 0.7705132427757886, 0.6845471059286884, 0.5877852522924734, 0.48175367410171466, 0.368124552684678, 0.2486898871648555, 0.1253332335643039, 3.6739403974420594e-16, -0.12533323356430318, -0.24868988716485477, -0.36812455268467725, -0.48175367410171555, -0.5877852522924728, -0.6845471059286878, -0.770513242775788, -0.8443279255020156, -0.9048270524660197, -0.9510565162951534, -0.9822872507286885, -0.9980267284282714, -0.9980267284282716, -0.9822872507286886, -0.9510565162951538, -0.90482705246602, -0.8443279255020161, -0.7705132427757898, -0.6845471059286885, -0.5877852522924735, -0.4817536741017163, -0.3681245526846781, -0.2486898871648556, -0.125333233564304]

>>> 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):
    	#зона нечувствит
    	ytt = None
    	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)

    
>>> vyhod
[0, 0, -2062.187673241671, 3752502.2801429303, -6811818291.756302, 12365297400107.988, -2.2446367934687616e+16, 4.074624468431861e+19, -7.396548344503773e+22, 1.342674100065877e+26, -2.4373175906128126e+29, 4.4243923653693636e+32, -8.031471925583947e+35, 1.4579299475411253e+39, -2.6465382082285303e+42, 4.8041845216406776e+45, -8.720897679168846e+48, 1.5830794172859812e+52, -2.873718433161771e+55, 5.216578235381038e+58, -9.469504100271485e+61, 1.7189717830141683e+65, -3.1203999275043293e+68, 5.664372041346515e+71, -1.0282371288365432e+75, 1.866529220539488e+78, -3.3882566904288307e+81, 6.150604701981334e+84, -1.116501542132187e+88, 2.026753065730243e+91, -3.6791064180730074e+94, 6.6785758286883414e+97, -1.212342618860748e+101, 2.2007306096497498e+104, -3.994922838562404e+107, 7.25186827324016e+110, -1.3164107437767657e+114, 2.3896424769952626e+117, -4.3378491058778625e+120, 7.874372441280753e+123, -1.4294121310025034e+127, 2.5947706379059605e+130, -4.710212343459617e+133, 8.550312692910703e+136, -1.552113616450096e+140, 2.8175071075087226e+143, -5.1145394362419765e+146, 9.284276009512575e+149, -1.6853478616277227e+153, 3.059363392237472e+156, -5.5535741782845336e+159, 1.008124312135154e+163, -1.8300190041432215e+166, 3.321980747029509e+169, -6.030295892364987e+172, 1.0946622307185519e+176, -1.9871087932498902e+179, 3.607141313004942e+182, -6.547939647887588e+185, 1.1886286095251596e+189, -2.1576832520707578e+192, 3.916780211210369e+195, -7.110018214307417e+198, 1.2906611114684283e+202, -2.3428999117116665e+205, 4.252998674495826e+208, -7.72034589904807e+211, 1.401452136780036e+215, -2.5440156663544065e+218, 4.618078306638927e+221, -8.38306443167872e+224, 1.5217535216899362e+228, -2.7623953026351666e+231, 5.0144965654797075e+234, -9.102671070002446e+237, 1.652381640443558e+241, -2.999520761189287e+244, 5.444943575135833e+247, -9.8840491187859e+250, 1.7942229452788257e+254, -3.257001193211853e+257, 5.912340381387176e+260, -1.0732501068232718e+264, 1.948239981957719e+267, -3.536583880278735e+270, 6.419858774112167e+273, -1.1653784577080823e+277, 2.1154779216742002e+280, -3.840166091530762e+283, 6.9709428112924446e+286, -1.2654151544507626e+290, 2.2970716536645406e+293, -4.1698079586848016e+296, 7.569332190649337e+299, -1.374039053598805e+303, 2.494253486651031e+306, -inf, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
```