Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

26 KiB

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

Бушманов Артём, А-01-23

1. Запуск интерактивной оболочки IDLE. Создание рабочего каталога.

>>>import os
>>>os.chdir('/Users/ArtyomBushmanov/python-labs/TEMA7')

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

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

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

2.1. Функция – без аргументов.

>>>def uspeh():
    """Подтверждение успеха операции"""
    
    print('Выполнено успешно!')

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

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

Видно, что help вернуло имя функции и то описание, которое было указано в тройных кавычках при её определении. Это называется docstring или документ-строка. Они используются для написания документации. Она должна быть первой строкой внутри блока.

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

>>>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)
16  больше  5

Выполнение функции с аргументами - символьными строками:

>>>sravnenie("big", "small")
big  меньше  small

Из-за не конкретизированной функции, мы можем задать любые данные, которые можно сравнить. Если что-то нельзя сравнить, вернется TypeError.

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

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

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

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

>>>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)  #Сложение списков
>>>print(q)
[1, 2, -1, -2, 0, 2, -1, -1]
>>>slozh((1, 2), (5, 0), (-1, -3), (-6, 2)) # Сложение кортежей
(1, 2, 5, 0, -1, -3, -6, 2)
>>>slovar1 = {'a' : 1}; slovar2 = {'b' : 2}; slovar3 = {'c' : 3}; slovar4 = {'d' : 4}
>>>slozh(slovar1, slovar2, slovar3, slovar4) # Сложение словарей
Traceback (most recent call last):
  File "<pyshell#44>", line 1, in <module>
    slozh(slovar1, slovar2, slovar3, slovar4)
  File "<pyshell#35>", line 3, in slozh
    return a1 + a2 + a3 + a4
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
>>>slozh({1,1,1,1}, {2}, {"abc", True, None}, {6, 6, "a"}) # Сложения множеств
Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    slozh({1,1,1,1}, {2}, {"abc", True, None}, {6, 6, "a"})
  File "<pyshell#35>", line 3, in slozh
    return a1 + a2 + a3 + a4
TypeError: unsupported operand type(s) for +: 'set' and 'set'

Функция slozh(a1, a2, a3, a4) складывает аргументы с помощью оператора +. Для кортежей оператор + определён, поэтому функция будет работать — кортежи просто склеиваются в один. Для словарей и множеств оператор + не определён, поэтому при попытке вызвать функцию с такими аргументами возникает ошибка TypeError. Следовательно, данная реализация функции применима для кортежей (как и для чисел, строк и списков), но не может напрямую использоваться для словарей и множеств.

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

>>>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 pylab as plt
>>>plt.plot(spsy, label = "Выходной сигнал")
[<matplotlib.lines.Line2D object at 0x0000025286FC2E30>]
>>>plt.show()

График

Пункт 3. Функции как объекты.

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

>>>dir(inerz)
['__annotations__', '__builtins__', '__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__']
>>>inerz.__doc__
' Модель устройства с памятью:\nx- текущее значение вх.сигнала,\nT -постоянная времени,\nypred - предыдущее значение выхода устройства'
>>>help(inerz)
Help on function inerz in module __main__:

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

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

>>>fnkt = sravnenie
>>>v = 16
>>>fnkt(v, 23)
16  меньше  23

В данном случае происходит присвоение функции sravnenie переменной fnkt. Функции можно передавать в переменные, как и любые другие объекты. После этого переменная fnkt ссылается на ту же самую функцию, что и sravnenie.

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

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

Программа выводит сообщение "Функция 2", потому что переменная typ_fun не равна 1, и выполняется блок else, в котором функция func определена как выводящая. Функция становится доступной только после того, как интерпретатор достигает строки с её определением.

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

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

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

Python передаёт ссылку на объект функции logistfun в переменную fff. Внутри функции выполняется операция: a + fff(c, b), что эквивалентно -3 + logistfun(0.7, 1)

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

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

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

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

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

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

Создается список b1234, содержащий 4 элемента: b1, b2, b3, b4. Затем Оператор * выполняет распаковку списка b1234. Вместо передачи одного аргумента (списка), передаются 4 отдельных аргумента.

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

>>>dic4 = {"a1":1,"a2":2,"a3":3,"a4":4}
>>>qqq = slozh(**dic4)  #Перед ссылкой на словарь надо ставить две звездочки
>>>print(qqq)
10

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

>>>e1=(-1,6);dd2={'a3':3,'a4':9}
>>>qqqq=slozh(*e1,**dd2)
>>>print(qqqq)
17

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

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

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

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

>>>func4(-1, 2, 0, 3, 6)
-7

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

>>>def func5(a,b=7,**slovar7): #Аргументы: a-позиционный, b- по умолчанию + кортеж
    """Словарь - сборка именованных аргументов!"""
    smm = 0
    for key, value in slovar7.items():
        smm += value
    return a * smm + b

>>>func5(-1, 2, x=0, y=3, z=6)
-7

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

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

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

Значени a не изменилось

  • Пример со списком:
>>>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)
Traceback (most recent call last):
  File "<pyshell#170>", line 1, in <module>
    func2(kort)
  File "<pyshell#166>", line 2, in func2
    sps[1] = 99
TypeError: 'tuple' object does not support item assignment

Кортеж - неизменяемая коллекция, поэтому значение заменить не получилось.

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

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

Анонимные функции или по-другому их называют лямбда-функциями – это функции без имени (поэтому их и называют анонимными), определяемые по следующей схеме: lambda [<Аргумент1>[,<Аргумент2>,…]]:<Возвращаемое значение или выражение> Анонимная функция возвращает ссылку на объект-функцию, которую можно присвоить другому объекту.

>>>import math
>>>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

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

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

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

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

>>>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#196>", line 1, in <module>
    print(alp.__next__())
StopIteration

В конце вывело ошибку, т.к. все возможные значения уже были выведены на экран (диапазон закончился).

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

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

  • Одноименные локальный и глобальный объекты:
>>>def func8(arg):
    locl = 15
    print(glb)
    glb = 8
    return locl*arg

>>>res = func8(glb)
Traceback (most recent call last):
  File "<pyshell#209>", line 1, in <module>
    res = func8(glb)
  File "<pyshell#208>", line 3, in func8
    print(glb)
UnboundLocalError: local variable 'glb' referenced before assignment

Мы получили ошибку потому, что на локальную переменную glb код ссылается перед назначением. Если переменной присваивается значение внутри функции, она считается локальной для всей функции. Даже если такое же имя есть в глобальной области, внутри функции будет создана новая локальная переменная.

  • Переопределение локализации объекта:
>>>glb = 11
>>>def func7(arg):
    locl = 15
    global glb
    print(glb)
    glb = 8
    return locl * arg

>>>res = func7(glb)
11
>>>print(res)
165
>>>print(glb)
8

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

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

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

>>>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__', 'os', 'uspeh', 'sravnenie', 'n', 'm', 'logistfun', 'v', 'w', 'z', 'slozh', 'b1', 'b2', 'b3', 'b4', 'q', 'slovar1', 'slovar2', 'slovar3', 'slovar4', 'inerz', 'sps', 'spsy', 'TT', 'yy', 'xx', 'plt', 'fnkt', 'typ_fun', 'func', 'fun_arg', 'zz', 'b1234', 'qq', 'dic4', 'qqq', 'e1', 'dd2', 'qqqq', 'func4', 'func5', 'a', 'func3', 'sps1', 'func2', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'mm', 'alp', 'glb', 'func7', 'func8', 'res'])
dict_keys(['arg', 'loc1', 'glb'])

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

Проверка наличие объекта glb в перечне глобальных объектов:

>>>'glb' in globals().keys()
True

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

>>>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__', 'os', 'uspeh', 'sravnenie', 'n', 'm', 'logistfun', 'v', 'w', 'z', 'slozh', 'b1', 'b2', 'b3', 'b4', 'q', 'slovar1', 'slovar2', 'slovar3', 'slovar4', 'inerz', 'sps', 'spsy', 'TT', 'yy', 'xx', 'plt', 'fnkt', 'typ_fun', 'func', 'fun_arg', 'zz', 'b1234', 'qq', 'dic4', 'qqq', 'e1', 'dd2', 'qqqq', 'func4', 'func5', 'a', 'func3', 'sps1', 'func2', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'mm', 'alp', 'glb', 'func7', 'func8', 'res', 'hh', 'func9'])
locl_func9_1: dict_keys(['arg1', 'loc1', 'glb1'])# Содержит только объекты, определенные внутри func9_1, а также объект, переданный как аргумент функции

loc_func9: dict_keys(['arg2', 'arg3', 'func9_1', 'loc1', 'glb'])# Содержит все то же, что и locl_func9_1, но еще и arg3, переданный func9 и саму func9_1
glob_func9: dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'os', 'uspeh', 'sravnenie', 'n', 'm', 'logistfun', 'v', 'w', 'z', 'slozh', 'b1', 'b2', 'b3', 'b4', 'q', 'slovar1', 'slovar2', 'slovar3', 'slovar4', 'inerz', 'sps', 'spsy', 'TT', 'yy', 'xx', 'plt', 'fnkt', 'typ_fun', 'func', 'fun_arg', 'zz', 'b1234', 'qq', 'dic4', 'qqq', 'e1', 'dd2', 'qqqq', 'func4', 'func5', 'a', 'func3', 'sps1', 'func2', 'kort', 'anfun1', 'math', 'anfun2', 'anfun3', 'mm', 'alp', 'glb', 'func7', 'func8', 'res', 'hh', 'func9']) # Тоже самое, что и glob_func9_1

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

>>>znach=input('k1,T,k2,Xm,A,F,N=').split(',')
k1,T,k2,Xm,A,F,N=6, 5, 8, 10, 3, 0.5, 1500
>>>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])
>>>import math
>>>vhod =[]
>>>for i in range(N):
    vhod.append(A*math.sin((2*i*math.pi)/F))
 
>>>print(vhod)
[0.0, -1.4695761589768238e-15, -2.9391523179536475e-15, , 2.9174217636433927e-12, -4.033155768249364e-12, -6.979687886698152e-14, -7.0203744107597384e-12]


>>>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 -gran <= xtt <= gran:
        ytt = 0
    elif xtt > gran:
        ytt = xtt - gran
    else:  # 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)
y= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27.421883254961507, -159.8455361225524, 760.8726454041447, -3488.73566888214, 15869.602621377877, -72062.25788892987, 327102.1123783949, -1484643.5574000787, 6738340.865317245,..., nan, nan, nan, nan, nan]

7. Завершение сеанса в среде IDLE