Python урок 3. функции и процедуры

Содержание:

Функции в роли процедуры

Подпрограммы прежде всего необходимы в ситуации, когда в разных частях программы необходимо выполнять одни и те же действия несколько раз. В таком случае повторяемые операторы оформляются в виде функции или процедуры, к которой можно обращаться и вызывать ее выполнение из разных частей программы.
В python существует два вида реализации подпрограмм: функции в роли процедуры и функции в классическом понимании.
Функция в роли процедуры призвана не возвратить значение в основную программу, а вывести его, либо выполнить какие-либо действия с глобальными переменными, при этом не возвращая полученные значения основной программе (не используя ключевое слово ).

Рассмотрим синтаксис функции-процедуры на примере:

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

Решение: 

def Err():  # определение процедуры
  print ( "Ошибка: неверные данные" ) 
n = int ( input('введите положительное число') ) 
if n < : 
  Err() # вызов процедуры
  • Процедура — вспомогательный алгоритм, выполняющий некоторые действия.
  • Это поименованный фрагмент программы, который можно вызвать.
  • Процедура должна быть определена к моменту её вызова. Определение процедуры начинается со служебного слова def.
  • Вызов процедуры осуществляется по ее имени, за которым следуют круглые скобки, например, Err().
  • В одной программе может быть сколько угодно много вызовов одной и той же процедуры.
  • Использование процедур сокращает код и повышает удобочитаемость.

Процедура с параметрами

Как используются в Python параметры процедуры, рассмотрим на примере.

Пример: Написать процедуру, которая печатает 60 раз указанный символ (введенный с клавиатуры), каждый с новой строки.

Решение: 

1
2
3
4
5
def printChar(s):
   for i in range(60):
      print (s) 
sim = input('введите символ')
printChar(sim)
  • Глобальная переменная — если ей присвоено значение в основной программе (вне процедуры).
  • Локальная переменная (внутренняя) известна только на уровне процедуры, обратиться к ней из основной программы и из других процедур нельзя.
  • Параметры процедуры — локальные переменные. В программе s — локальная переменная.

Задание Python 3_0:
Создать процедуру, которая вычисляет разность двух вводимых пользователем числа. Выполнить задание двумя способами: 1) процедура без параметров: числа — глобальные переменные, определенные в основной программе; 2) процедура с параметрами: числа — параметры процедуры.

Локальные и глобальные переменные

Примеры использования локальных и глобальных переменных:

1
2
3
4
x = 3 # глобальная переменная
def pr(): # процедура без параметров
  print (x) # вывод значения глобальной переменной
pr()
1
2
3
4
5
x = 3  # глобальная переменная
def pr(a): # процедура с параметром
  a = 4 # локальная переменная
  print (a) # 4
pr(x) # передача параметра глобальной переменной (3)

Существует возможность изменить значение глобальной переменной (не создавая локальную). В процедуре с помощью слова global:

1
2
3
4
5
6
x = 3 # глобальная переменная
def pr(): # процедура без параметров
  global x
  x = 1
  print (x) # вывод измененного значения глобальной переменной (1)
pr(x)

Задание Python 3_1:
Напишите процедуру, которая выводит на экран в столбик все цифры переданного ей числа, начиная с последней:

число: 4673
результат:
3
7
6
4

Задание Python 3_2:
Напишите процедуру, которая выводит на экран все делители переданного ей числа (в одну строчку).

Задание Python 3_3:
Составить программу с процедурой для вычисления степени числа (входные параметры: число и степень).

Рекомендации: для вычисления степени числа можно использовать функцию

Задание Python 3_4:
Напишите процедуру, которая принимает параметр – натуральное число N – и выводит первые N чисел Фибоначчи.

Пример использования ключевого слова :
Поменять значений двух переменных.

Решение:

  • Решение 1:
def Swap():
    global x,y
    t = x
    x = y
    y = t
x=3
y=5    
Swap() 
print(x,y)

Решение 2:

def Swap():
    global x,y
    (x, y) = (y, x)
(x,y)=(3,5)
Swap() 
print(x,y)

Задание Python 3_5:
Создайте процедуру без параметров , которая добавляет введенную цифру (0D (0global для работы с глобальными переменными.

Ожидаемый результат:

введите D (0>>2  >>>4  
результат: 42

Функции придают программе структуру

Польза функций не только в возможности многократного вызова одного и того же кода из разных мест программы

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

Пусть надо написать программу, вычисляющую площади разных фигур. Пользователь указывает, площадь какой фигуры он хочет вычислить. После этого вводит исходные данные. Например, длину и ширину в случае прямоугольника. Чтобы разделить поток выполнения на несколько ветвей, следует использовать оператор if-elif-else:

figure = input("1-прямоугольник, 
2-треугольник, 3-круг: ")

if figure == '1':
  a = float(input("Ширина: "))
  b = float(input("Высота: "))
  print("Площадь: %.2f" % (a*b))
elif figure == '2':
  a = float(input("Основание: "))
  h = float(input("Высота: "))
  print("Площадь: %.2f" % (0.5 * a * h))
elif figure == '3':
  r = float(input("Радиус: "))
  print("Площадь: %.2f" % (3.14 * r**2))
else:
  print("Ошибка ввода")

Здесь нет никаких функций, и все прекрасно. Но напишем вариант с функциями:

def rectangle():
    a = float(input("Ширина: "))
    b = float(input("Высота: "))
    print("Площадь: %.2f" % (a*b))

def triangle():
    a = float(input("Основание: "))
    h = float(input("Высота: "))
    print("Площадь: %.2f" % (0.5 * a * h))

def circle():
    r = float(input("Радиус: "))
    print("Площадь: %.2f" % (3.14 * r**2))

figure = input("1-прямоугольник, 
2-треугольник, 3-круг: ")
if figure == '1':
  rectangle()
elif figure == '2':
  triangle()
elif figure == '3':
  circle()
else:
  print("Ошибка ввода")

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

Если нам когда-нибудь захочется вычислять площадь треугольника по формуле Герона, а не через высоту, то не придется искать код во всей программе (представьте, что она состоит из тысяч строк кода как реальные программы). Мы пойдем к месту определения функций и изменим тело одной из них.

Если понадобиться использовать эти функции в какой-нибудь другой программе, то мы сможем импортировать их туда, сославшись на данный файл с кодом (как это делается в Python, будет рассмотрено позже).

Функция filter():

Функция filter() используется для создания списка, состоящего из значений, для которых функция возвращает true. Синтаксис этого следующий:

filter(function, iterables)

Так же, как и map(), эта функция может использовать в качестве параметра пользовательские функции, а также lambda-функции.

Пример:

def func(x):
    if x>=3:
        return x
y = filter(func, (1,2,3,4))  
print(y)
print(list(y))

Результат:

<filter object at 0x00000284B9BBCC50>

Как видите, y — это объект типа функции filter, а выходной список — это список значений, которые являются истинными для условия (x>=3).

Использование lambda-функций совместно с filter():

Lambda-функция, которая используется в качестве параметра, фактически определяет условие, которое необходимо проверить.

Пример:

y = filter(lambda x: (x>=3), (1,2,3,4))
print(list(y))

Результат:

Приведенный выше код выдает тот же результат, что и предыдущая функция.

Протоколы

Такие термины как «протокол итератора» или «протокол дескрипторов» уже привычны и используются давно.
Теперь можно описывать протоколы в виде кода и проверять их соответствие на этапе статического анализа.

Стоит отметить, что начиная с Python 3.6 в модуль typing уже входят несколько стандартных протоколов.
Например, (требующего наличие метода ), (требует ) и некоторых других.

Описание протокола

Протокол описывается как обычный класс, наследующийся от Protocol. Он может иметь методы (в том числе с реализацией) и поля.
Реальные классы, реализующие протокол могут наследоваться от него, но это не обязательно.

Мы можете комбинировать протоколы с помощью наследования, создавая новые.
Однако в этом случае вы так же должны явно указать Protocol как родительский класс

Дженерики, self-typed, callable

Протоколы как и обычные классы могут быть Дженериками. Вместо указания в качестве родителей и можно просто указать

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

Проверки в рантайме

Хотя протоколы и рассчитаны в первую очередь на использование статическими анализаторами, иногда бывает нужно проверить принадлежность класса нужному протоколу.
Чтобы это было возможно, примените к протоколу декоратор и / проверки начнут проверять соответствие протоколу

Однако такая возможность имеет ряд ограничений на использование. В частности, не поддерживаются дженерики

all(iterable)

Возвращает True если все элементы iterable равны True:

print(all()) # True
print(all()) # False

print(all(map(lambda x: x % 2 == 0, ))) # True

1
2
3
4

print(all(True,True,True))# True

print(all(True,False,True))# False

print(all(map(lambdaxx%2==,2,4,6,8)))# True

Другие типы данных преобразуются к bool:

print(all()) # True
print(all()) # False
print(all(, []])) # False

1
2
3

print(all(1,2,3))# True

print(all(1,2,))# False

print(all(1,))# False

Если iterable пустой, то функция вернёт True:

print(all([])) # True

1 print(all())# True

Функция all() эквивалента следующему коду:

def all(iterable):
for element in iterable:
if not element:
return False
return True

1
2
3
4
5

def all(iterable)

forelement initerable

ifnotelement

returnFalse

returnTrue

max

  • max(iterable, *)
  • max(arg1, arg2, *args)

Функция возвращает максимальный элемент. Две версии функции отличаются аргументами: с итерируемым объектом и со списком аргументов.

print(max()) # 8
print(max(3, 5, 8, 2)) # 8

1
2

print(max(3,5,8,2))# 8

print(max(3,5,8,2))# 8

Если коллекция пустая возникнет исключение

print(max([], )) # ValueError

1 print(max(,))# ValueError

Именованный аргумент default используется чтобы избежать исключения. Функция max возвращает default только если коллекция пустая:

print(max([], default=0)) # 0
print(max(, default=5)) # 3

1
2

print(max(,default=))# 0

print(max(2,3,default=5))# 3

Порядок элементов изменяется аргументом key. Переданная в key функция применяется к каждому элементу. Результат функции используется для определения порядка элементов:

def neg(n):
return -n

print(max(, key=neg)) # 2

1
2
3
4

def neg(n)

return-n

print(max(3,5,8,2,key=neg))# 2

print

О функции print мы уже немного
говорили на предыдущем занятии, здесь рассмотрим подробнее различные
возможности ее использования. Например, эту функцию можно записывать в таких
вариациях:

print(1)
print(1, 2)
print(1, 2, 3)

И так далее,
число аргументов может быть произвольным. Соответственно все эти значения в
строчку будут выведены в консоли. Причем, значения разделяются между собой
пробелом. Это разделитель, который используется по умолчанию. Если нужно
изменить значение этого разделителя, то для этого используется специальный
именованный аргумент sep:

print(1, 2, 3, sep=",")
print(1, 2, 3, sep="-")
print(1, 2, 3, sep="***")

то есть, здесь можно прописывать самые разные строки-разделители.

Далее, вы уже
заметили, что каждый вызов функции print делает перевод
строки. Этот символ автоматически добавляет в конец выводимых данных. Но, мы
также можем его изменить. Для этого используется именованный аргумент end:

print(1, 2, 3, sep=",", end=':')
print(1, 2, 3, sep="-", end='--end--\n')
print(1, 2, 3, sep="***")

Смотрите, теперь
у нас после первой строчки нет перевода строки, а поставлено двоеточие с
пробелом, которые мы указали в аргументе end. После второго
вывода в конце была добавлена строчка и указан символ ‘\n’ перевода
строки.

В качестве
примера все это можно использовать для более гибкого вывода значений с помощью print:

name = "Федор"
print("Имя", name, sep=":")

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

name = "Федор"; age = 18
print("Имя %s, возраст %d"%(name, age))

В результате,
вместо спецификатора %s будет подставлена первая переменная,
указанная в скобках, в виде строки, а вместо %d – вторая
переменная age в виде целого
числа. То есть, для каждого типа данных существует свой спецификатор. Наиболее
употребительные, следующие:

  • %d, %i, %u – для вывода целочисленных
    значений;

  • %f – для вывода
    вещественных значений;

  • %s
    – для
    вывода строк;

  • %%
    — для
    вывода символа %

Вот основные
возможности функций input и print в Python.

Видео по теме

Python 3 #1: установка и запуск интерпретатора языка

Python 3 #2: переменные, оператор присваивания, типы данных

Python 3 #3: функции input и print ввода/вывода

Python 3 #4: арифметические операторы: сложение, вычитание, умножение, деление, степень

Python 3 #5: условный оператор if, составные условия с and, or, not

Python 3 #6: операторы циклов while и for, операторы break и continue

Python 3 #7: строки — сравнения, срезы строк, базовые функции str, len, ord, in

Python 3 #8: методы строк — upper, split, join, find, strip, isalpha, isdigit и другие

Python 3 #9: списки list и функции len, min, max, sum, sorted

Python 3 #10: списки — срезы и методы: append, insert, pop, sort, index, count, reverse, clear

Python 3 #11: списки — инструмент list comprehensions, сортировка методом выбора

Python 3 #12: словарь, методы словарей: len, clear, get, setdefault, pop

Python 3 #13: кортежи (tuple) и операции с ними: len, del, count, index

Python 3 #14: функции (def) — объявление и вызов

Python 3 #15: делаем «Сапер», проектирование программ «сверху-вниз»

Python 3 #16: рекурсивные и лямбда-функции, функции с произвольным числом аргументов

Python 3 #17: алгоритм Евклида, принцип тестирования программ

Python 3 #18: области видимости переменных — global, nonlocal

Python 3 #19: множества (set) и операции над ними: вычитание, пересечение, объединение, сравнение

Python 3 #20: итераторы, выражения-генераторы, функции-генераторы, оператор yield

Python 3 #21: функции map, filter, zip

Python 3 #22: сортировка sort() и sorted(), сортировка по ключам

Python 3 #23: обработка исключений: try, except, finally, else

Python 3 #24: файлы — чтение и запись: open, read, write, seek, readline, dump, load, pickle

Python 3 #25: форматирование строк: метод format и F-строки

Python 3 #26: создание и импорт модулей — import, from, as, dir, reload

Python 3 #27: пакеты (package) — создание, импорт, установка (менеджер pip)

Python 3 #28: декораторы функций и замыкания

Python 3 #29: установка и порядок работы в PyCharm

Python 3 #30: функция enumerate, примеры использования

Важность функций

Абстракция

Человек бежит, машина едет, корабль плывёт, а самолёт летит. Всё это – объекты реального мира, которые выполняют однотипные действия. В данном случае, они перемещаются во времени и пространстве. Мы можем абстрагироваться от их природы, и рассматривать эти объекты с точки зрения того, какое расстояние они преодолели, и сколько времени на это ушло.

Мы можем написать функцию, которая вычисляет скорость в каждом конкретном случае

Нам не важно, кто совершает движение: и для человека и для самолёта средняя скорость будет рассчитываться одинаково

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

Возможность повторного использования

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

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

Всего 10 таких сортировок, и привет, лишние 60 строк кода.

Модульность

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

В программировании модульность строится на использовании функций. Для каждой подзадачи – своя функция. Такая компоновка в разы улучшает читабельность кода и уменьшает сложность его дальнейшей поддержки.

Допустим, мы работаем с базой данных. Нам нужна программа, которая считывает значения из базы, обрабатывает их, выводит результат на экран, а затем записывает его обратно в базу.

Без применения модульности получится сплошная последовательность инструкций:

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

Это и называется модульностью.

Пространство имен

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

Пример из жизни: в ВУЗе учатся два человека с совпадающими ФИО. Их нужно как-то различать. Если сделать пространствами имён группы этих студентов, то проблема будет решена. В рамках своей группы ФИО этих студентов будут уникальными.

Возвращает тип объекта и является собственным метаклассом языка Python.

Параметры:

  • — объект, тип которого определяется
  • — имя для создаваемого типа
  • — кортеж с родительскими классами
  • — словарь, будет являться пространством имён для тела класса

Возвращаемое значение:

  • тип объекта, при ,
  • объект нового типа при .

Вызов класса с одним аргументом:

Класс с одним аргументом возвращает тип объекта. Возвращаемое значение — это как правило, тот же объект, что и возвращаемый .

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

Примеры использования класса при вызове с одним аргументом.

>>> x = 1
>>> type(x)
# <class 'int'>

>>> x = 1, 2, 3
>>> type(x)
# <class 'list'>

# проверка типа объекта
>>> x = 1
>>> isinstance(x, int)
# True
>>> x = 1, 2, 3
>>> isinstance(x, list)
# True

Вызов класса с тремя аргументами:

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

Другими словами класс , вызванный с тремя аргументами на самом деле ! Класс это метакласс, который Python внутренне использует для создания всех классов.

Все, с чем имеем дело в Python, является объектом. Сюда входят функции и классы целые числа, строки и т.д. Все они объекты. И все они созданы из класса.

# type - это тип всех типов, для 
# которых не указан явно иной метакласс
>>> type(type)
# <class 'type'>
>>> type(object)
# <class 'type'>
>>> type(list)
# <class 'type'>
>>> type(int)
# <class 'type'>
>>> class Bar(object): pass
>>> type(Bar)
# <class 'type'>

В общем — это класс всех классов в языке Python и является собственным метаклассом. Класс нельзя воспроизвести на чистом Python.

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

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

Важно понимать, что тип, как и другие сущности в Python, тоже является объектом. Изменено в Python 3.6: подклассы, которые не переопределяют, больше не могут использовать форму с одним аргументом для получения типа объекта

Изменено в Python 3.6: подклассы, которые не переопределяют, больше не могут использовать форму с одним аргументом для получения типа объекта.

Число Пи из библиотеки math

Первой важной математической константой является число Пи (π). Оно обозначает отношение длины окружности к диаметру, его значение 3,141592653589793

Чтобы получить к нему доступ, сначала импортируем библиотеку math следующим образом:

Python

import math

1 importmath

Затем можно получить доступ к константе, вызывая :

Python

math.pi

1 math.pi

Вывод

Shell

3.141592653589793

1 3.141592653589793

Данную константу можно использовать для вычисления площади или длины окружности. Далее представлен пример простого кода, с помощью которого это можно сделать:

Python

import math

radius = 2
print(‘Площадь окружности с радиусом 2 равна:’, math.pi * (radius ** 2))

1
2
3
4

importmath

radius=2

print(‘Площадь окружности с радиусом 2 равна:’,math.pi*(radius**2))

Вывод

Shell

Площадь окружности с радиусом 2 равна: 12.566370614359172

1 Площадьокружностисрадиусом2равна12.566370614359172

Мы возвели радиус во вторую степень и умножили значение на число Пи, как и следовало сделать в соответствии с формулой πr2.

Python Tutorial

Python HOMEPython IntroPython Get StartedPython SyntaxPython CommentsPython Variables
Python Variables
Variable Names
Assign Multiple Values
Output Variables
Global Variables
Variable Exercises

Python Data TypesPython NumbersPython CastingPython Strings
Python Strings
Slicing Strings
Modify Strings
Concatenate Strings
Format Strings
Escape Characters
String Methods
String Exercises

Python BooleansPython OperatorsPython Lists
Python Lists
Access List Items
Change List Items
Add List Items
Remove List Items
Loop Lists
List Comprehension
Sort Lists
Copy Lists
Join Lists
List Methods
List Exercises

Python Tuples
Python Tuples
Access Tuples
Update Tuples
Unpack Tuples
Loop Tuples
Join Tuples
Tuple Methods
Tuple Exercises

Python Sets
Python Sets
Access Set Items
Add Set Items
Remove Set Items
Loop Sets
Join Sets
Set Methods
Set Exercises

Python Dictionaries
Python Dictionaries
Access Items
Change Items
Add Items
Remove Items
Loop Dictionaries
Copy Dictionaries
Nested Dictionaries
Dictionary Methods
Dictionary Exercise

Python If…ElsePython While LoopsPython For LoopsPython FunctionsPython LambdaPython ArraysPython Classes/ObjectsPython InheritancePython IteratorsPython ScopePython ModulesPython DatesPython MathPython JSONPython RegExPython PIPPython Try…ExceptPython User InputPython String Formatting

Scope and Lifetime of variables

Scope of a variable is the portion of a program where the variable is recognized. Parameters and variables defined inside a function are not visible from outside the function. Hence, they have a local scope.

The lifetime of a variable is the period throughout which the variable exits in the memory. The lifetime of variables inside a function is as long as the function executes.

They are destroyed once we return from the function. Hence, a function does not remember the value of a variable from its previous calls.

Here is an example to illustrate the scope of a variable inside a function.

Output

Value inside function: 10
Value outside function: 20

Here, we can see that the value of x is 20 initially. Even though the function changed the value of x to 10, it did not affect the value outside the function.

This is because the variable x inside the function is different (local to the function) from the one outside. Although they have the same names, they are two different variables with different scopes.

On the other hand, variables outside of the function are visible from inside. They have a global scope.

We can read these values from inside the function but cannot change (write) them. In order to modify the value of variables outside the function, they must be declared as global variables using the keyword .

Примеры создания и изменения классов «на лету» при помощи type():

Например, следующие два определения создают идентичные объекты.

>>> class Foo(object):
...       bar = True
>>> Foo = type('Foo', (), {'bar'True})

Класс , созданный через метакласс можно использовать как обычный класс:

>>> Foo
# <class '__main__.Foo'>
>>> f = Foo()
>>> f.bar
# True

# можно наследоваться от него
>>>   class FooChild(Foo): pass
...
>>> FooChild
# <class '__main__.FooChild'>
>>> FooChild.bar # bar унаследован от Foo
# True

Добавим методы в класс . Для этого определим функцию и добавим ее как атрибут.

>>> def echo_bar(self):
...       print(self.bar)
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar' echo_bar})
>>> hasattr(Foo, 'echo_bar')
# False
>>> hasattr(FooChild, 'echo_bar')
# True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
# True

# после динамического создания класса добавим еще один метод 
>>> def echo_bar_more(self):
...       print('yet another method')
...
>>> FooChild.echo_bar_more = echo_bar_more
>>> hasattr(FooChild, 'echo_bar_more')
# True

Аргументы

Python допускает три типа параметров в определении функции.

  1. Формальные аргументы: те, которые мы видели в примерах до сих пор.
  2. Переменное количество аргументов без ключевых слов: например, def add(*args)
  3. Переменное количество аргументов ключевых слов или именованных аргументов: например, def add(**kwargs)

Некоторые важные моменты относительно переменных аргументов в Python:

  • Порядок аргументов должен быть формальным, * args и ** kwargs.
  • Не обязательно использовать имена параметров переменных как args и kwargs. Однако лучше всего использовать их для лучшей читаемости кода.
  • Тип args — кортеж. Таким образом, мы можем передать кортеж для отображения с переменной * args.
  • Тип кваргов — дикт. Таким образом, мы можем передать словарь для сопоставления с переменной ** kwargs.

Вот простой пример.

def add(x, y, *args, **kwargs):
    sum = x + y
    for a in args:
        sum += a

    for k, v in kwargs.items():
        sum += v
    return sum


total = add(1, 2, *(3, 4), **{"k1": 5, "k2": 6})
print(total)  # 21

Функция как объект в Python

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

>>> # исходный список
>>> a = 1, 2, 3, 4, 5
>>> # функция, которая возводит в квадрат переданное ей число 
>>> sq = lambda x x**2
>>> # проверка работы функции в Python
>>> print(sq(5))
25

>>> # получение списка квадратов
>>> b = list(map(sq, a))
>>> print(b)
1, 4, 9, 16, 25

В нашем примере мы передали функции map в виде первого аргумента функцию sq. Последняя будет по очереди применяться ко всем элементам нашего списка a.

Кроме того, в Python функция является специальным объектом, имеющим метод __call__(). Представьте, что мы создали следующий класс:

class DemoCall():
def __call__(self):
return "Hello!"

Объект такого класса в Python мы сможем вызывать как функцию:

>>> hello = DemoCall()
>>> hello()
'Hello!'

Определение функции. Оператор def

В языке программирования Python функции определяются с помощью оператора def. Рассмотрим код:

def countFood():
    a = int(input())
    b = int(input())
    print("Всего", a+b, "шт.")

Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ.

Ключевое слово def сообщает интерпретатору, что перед ним определение функции. За def следует имя функции. Оно может быть любым, также как и всякий идентификатор, например, переменная. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа «посчитатьЕду» в переводе на русский.

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

После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела.

Функция внутри функции в Python

Функции в Python мы можем создавать, вызывать и возвращать из других функций. Кстати, на этом основана идея замыкания (closures) в Python.

Давайте создадим функцию, умножающую 2 числа:

def mul(a):
def helper(b):
return a * b
return helper

В этой функции в Python реализованы два важных свойства:
1) внутри функции mul() мы создаём ещё одну функцию helper();
2) функция mul() возвращает нам функцию helper() в качестве результата работы.

Вызов этой функции в Python:

>>>mul(4)(2)
8

Особенность заключается в том, что мы можем создавать на базе функции mul() собственные кастомизированные функции. Давайте создадим функцию в Python, умножающую на 3:

>>>three_mul = mul(3)
>>>three_mul(5)
15

В результате была построена функция three_mul(), умножающая на 3 любое переданное ей число.

Docstrings

The first string after the function header is called the docstring and is short for documentation string. It is briefly used to explain what a function does.

Although optional, documentation is a good programming practice. Unless you can remember what you had for dinner last week, always document your code.

In the above example, we have a docstring immediately below the function header. We generally use triple quotes so that docstring can extend up to multiple lines. This string is available to us as the attribute of the function.

For example:

Try running the following into the Python shell to see the output.

To learn more about docstrings in Python, visit Python Docstrings.

Карринг

Карринг (или каррирование, curring) — преобразование функции от многих переменных в функцию, берущую
свои аргументы по одному.

Примечание. Это преобразование было введено М. Шейнфинкелем и Г. Фреге и получило
своё название в честь математика Хаскелла Карри, в честь которого также назван и язык программирования
Haskell.

Карринг не относится к уникальным особенностям функционального программирования, так карринговое
преобразование может быть записано, например, и на языках Perl или C++. Оператор каррирования даже
встроен в некоторые языки программирования (ML, Haskell), что позволяет многоместные функции приводить к
каррированному представлению. Но все языки, поддерживающие замыкания, позволяют записывать
каррированные функции, и Python не является исключением в этом плане.

В листинге 8 представлен простейший пример с использованием карринга (файл curry1.py
в архиве python_functional.tgz в разделе «Материалы для скачивания»):

Листинг 8. Карринг
# -*- coding: utf-8 -*-

def spam( x, y ):
    print( 'param1={}, param2={}'.format( x, y ) )

spam1 = lambda x : lambda y : spam( x, y )

def spam2( x ) :
    def new_spam( y ) :
        return spam( x, y )
    return new_spam

spam1( 2 )( 3 )      # карринг
spam2( 2 )( 3 )

Вот как выглядят исполнение этих вызовов:

$ python curry1.py
param1=2, param2=3
param1=2, param2=3

Заключение

В этой статье были представлены некоторые возможности языка Python, позволяющие применять его для
написания программ, использующих стиль функционального программирования. Так, мы описали основные
приёмы функционального программирования и показали примеры их реализации в Python. Как и в предыдущих
статьях, примеры кода написаны таким образом, что могут успешно запускаться и исполняться в обеих версиях
Python.

В следующей статье мы обсудим вопросы организации параллельного исполнения кода в среде Python.

Похожие темы

  • Девид Мертц, Очаровательный Python: Функциональное программирование на языке Python, Часть 1
  • Девид Мертц, Очаровательный Python: Еще о функциональном программировании на Python, Часть 2
  • David Mertz, Charming Python: Functional programming in Python, Part 3
  • Тонкости использования языка Python: Часть 2. Типы данных.
  • Тонкости использования языка Python: Часть 4. Параллельное исполнение.
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector