Функции в программировании. Linux, Python, Django и все-все-все

29.07.2019

В этой статье я планирую рассказать о функциях, именных и анонимных, инструкциях def, return и lambda, обязательных и необязательных аргументах функции, функциях с произвольным числом аргументов.

Именные функции, инструкция def

Функция в python - объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def .

Определим простейшую функцию:

def add (x , y ): return x + y

Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.

Теперь мы ее можем вызвать:

>>> add (1 , 10 ) 11 >>> add ("abc" , "def" ) "abcdef"

Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!):

>>> def newfunc (n ): ... def myfunc (x ): ... return x + n ... return myfunc ... >>> new = newfunc (100 ) # new - это функция >>> new (200 ) 300

Функция может и не заканчиваться инструкцией return, при этом функция вернет значение :

>>> def func (): ... pass ... >>> print (func ()) None

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

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

>>> def func (a , b , c = 2 ): # c - необязательный аргумент ... return a + b + c ... >>> func (1 , 2 ) # a = 1, b = 2, c = 2 (по умолчанию) 5 >>> func (1 , 2 , 3 ) # a = 1, b = 2, c = 3 6 >>> func (a = 1 , b = 3 ) # a = 1, b = 3, c = 2 6 >>> func (a = 3 , c = 6 ) # a = 3, c = 6, b не определен Traceback (most recent call last): File "", line 1, in func(a=3, c=6) TypeError : func() takes at least 2 arguments (2 given)

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

>>> def func (* args ): ... return args ... >>> func (1 , 2 , 3 , "abc" ) (1, 2, 3, "abc") >>> func () () >>> func (1 ) (1,)

Как видно из примера, args - это из всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.

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

>>> def func (** kwargs ): ... return kwargs ... >>> func (a = 1 , b = 2 , c = 3 ) {"a": 1, "c": 3, "b": 2} >>> func () {} >>> func (a = "python" ) {"a": "python"}

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

Анонимные функции, инструкция lambda

Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda . Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():

>>> func = lambda x , y : x + y >>> func (1 , 2 ) 3 >>> func ("a" , "b" ) "ab" >>> (lambda x , y : x + y )(1 , 2 ) 3 >>> (lambda x , y : x + y )("a" , "b" ) "ab"

lambda функции, в отличие от обычной, не требуется инструкция return, а в остальном, ведет себя точно так же:

>>> func = lambda * args : args >>> func (1 , 2 , 3 , 4 ) (1, 2, 3, 4)

Начав писать главу про ООП, понял что совсем забыл освятить такой большой и нужный раздел Пайтона как функции. Тема это большая и обширная, потому, чтобы не сильно растягивать паузу между уроками, решил разделить ее на 2 части. Сначала расскажу основы, потом уже углубленные особенности Пайтоновского функциестроения.

Функции в Пайтоне объявляются не просто, а очень просто. Вот пример самой простой:

Def empty_func(): pass
Начинается объявление с ключевого слова def, что как не сложно догадаться является сокращением от define. После него идет имя функции. После имени в круглых скобках задается список параметров, в данном случае отсутствующих.
Тело функции пишется с отступом со следующей строки. учтите, что в Пайтоне функции с пустым телом запрещены, потому в качестве тела приведенной выше функции используется «пустой оператор» pass.
Теперь рассмотрим пример посерьезнее.

Def safe_div(x, y): """Do a safe division:-) for fun and profit""" if y != 0: z = x / y print z return z else: print "Yippie-kay-yay, motherf___er!"
В этом примере есть несколько нововведений. первое, что бросается в глаза - это строка документации (docstring), идущая сразу после тела функции.
Обычно эта строка занимает не одну строку исходного текста (простите за каламбур) и потому задается в тройных кавычках. Она предназначена для описания функции, ее предназначения, параметров и т.п. Все хорошие ИДЕ умеют с этой строкой работать. Получить к ней доступ можно и из самой программы, используя свойство __doc__:

Print safe_div.__doc__
Этим свойством (да, да, именно свойством, в Пайтоне даже функции на самом деле - классы) удобно пользоваться во время сеансов работы интерактивной консоли.
>>> from ftplib import FTP >>> print FTP.__doc__ An FTP client class. To create a connection, call the class using these argument: host, user, passwd, acct These are all strings, and have default value "". Then use self.connect() with optional host and port argument. # дальнейшее почикано мною:-)
Вернемся к нашей исходной функции. Суть ее очень проста, она принимает 2 параметра: х и у. Если у не равен 0, она делит х на у, выводит результат на экран и возвращает свое частное в виде результата. Результат функции возвращают с помощью команды return. Благодаря механизму кортежей, описанному в прошлом уроке, функции в Пайтоне могут возвращать одновременно множество объектов.
Если же делитель все-таки равен нулю, функция выводит сообщение об ошибке. Неверно было бы предположить что в этом случае функция ничего не вернет. Правильнее будет сказать что функция вернет «ничего»:) Иначе говоря, если в функции отсутствует оператор return, или же он вызван без параметров, то функция возвращает специальное значение None. В этом легко убедиться вызвав что-то типа print safe_div(10, 0).

Вот пример слегка посложнее, он взят из доклада-презентации Гвидо ван Россума.

Def gcd(a, b): "Нахождение НОД" while a != 0: a,b = b%a,a # параллельное определение return b
Данная функция находит наибольший общий делитель двух чисел.

В общем, следует учитывать, что параметры в функции Пайтоном передаются по ссылке. Еще одним, возможно нетривиальным фактом к которому придется привыкать - является тот факт что сами функции являются значением, которое можно присваивать. Если воспользоваться нашей функцией safe_div для дальнейших экспериментов, то можно написать следующий код.

Mystic_function = safe_div print mystic_function(10, 4)
Вот на этот раз и все, «за бортом» осталось еще много аспектов определения функций в Пайтоне, которые будут освещены в следующий раз.

Упражнения для проверки.
1. На основе существующей функции нахождения НОД, напишите функцию поиска НОК двух чисел.
2. Напишите подпрограмму табулирования функции, переданной в качестве аргумента. Так же аргументами задается начальное, конечное значение и шаг табуляции.

PS кстати, каков оптимальный объем «урока»? Что лучше - реже выходящие большие главы, или «лучше меньше да чаще».

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

Зачем нужны функции

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

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

Как написать первую функцию

В Python 3 для начинающих свое знакомство с программированием есть самая простая функция print(). Чтобы увидеть ее в действии вам понадобится среда разработки. Для этого скачайте дистрибутив языка с официального сайта и установите Python на компьютер.

Откройте меню «Пуск» и в списке программ найдите Python 3. Разверните его щелчком левой клавиши. В открывшемся списке найдите среду IDLE и запустите ее. Наберите print(«Hello, World!») и нажмите «Ввод». Интерпретатор вернет результат вашей первой функции.

Некоторые программисты предпочитают работать в консоли. Если вы относитесь к их числу, нажмите win+R и введите команду python.exe. Откроется обычный интерпретатор, только с интерфейсом cmd. Наберите программу описанным выше образом и нажмите Enter в конце, чтобы увидеть результат.

Как использовать def

Новые функции создаются с помощью инструкции def. Они так же эффективны, как и встроенные print() или open(), но отличаются от функций в компилирующих языках. Python def относится к исполняемым инструкциям. Это означает, что функции не существует, пока интерпретатор ее не увидит, и не перейдет к ее исполнению.

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

Теперь давайте напишем функцию, возвращающую фразу «Hello, World!», только с использованием def:

  • >>> def здравствуй_мир():
  • print(«Hello, World!»)
  • >>> здравствуй_мир() #вызов функции
  • Hello, World!

Синтаксис функций и return

Инструкция def в Python состоит из заголовка и пишется по следующим правилам:

  • >>>def <имя>

После заголовка следует блок инструкций, который начинается с обязательного отступа. В IDLE интерпретатор сделает его автоматически. Но в блокноте или другом текстовом редакторе вы можете забыть нажать Tab. Тогда функция не запустится. Программный код в блоке инструкции называется телом функции и выполняется каждый раз при ее вызове.

Также в теле иногда находится return:

  • def <имя>(аргумент 1, аргумент 2, аргумент N):
  • return <значение>

Return завершает работу функции и передает вызывающей программе объект-результат. Инструкция не является обязательной. Функция будет работать без return, и завершится, когда поток управления достигнет конца ее тела.

Параметры и аргументы

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

Аргументы внутри функции никак не связаны с объектами вне ее, поэтому в программировании их относят к локальным переменным. Область видимости ограничена блоком функции, который начинается с def и заканчивается return. Чтобы было понятнее, приведем пример:

  • x = 12 #присваиваем переменным ссылки на целочисленные объекты
  • y = 34
  • >>>def example(x,y): #создаем функцию с именем example
  • x = «Hello» #присваиваем значения аргументам x, y
  • y = «Python»
  • print(x, y, sep= «, »)
  • return None
  • >>>example(x, y) #вызываем функцию, не забыв указать параметры
  • Hello, Python
  • >>>print(x, y)
  • 12 34

Обратите внимание на предпоследнюю строчку кода. В интерпретаторе Python команда print() вернула переменные x и y из глобальной области видимости.

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

  • >>>def E_2(x, y):
  • return x + y
  • >>>E_2(«Hello, » «Python!») #чтобы слова были разделены, поставьте пробел перед закрывающей кавычкой
  • Hello, Python!
  • E_2(5, 4)

Как видно из примера с простой функцией E_2, результат полностью зависит от типа объектов x и y. В первом случае E_2 выполнила конкатенацию, а во втором - арифметическую операцию сложения. В этом заключается принцип полиморфизма и То, что объекты определяют синтаксический смысл, обуславливает гибкость и простоту языка. Не нужно тратить время на то, чтобы отдельно указать тип данных, с которым работает функция.

Правило LEGB

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

Правило LEGB объясняет схему разрешения имен:

  1. Как только интерпретатор находит переменную внутри инструкции def, он сначала выполняет поиск значений в локальной области видимости.
  2. Если поиск не дает результата, он переходит к области видимости любой всеобъемлющей инструкции def.
  3. Дальше интерпретатор двигается к глобальным именам в верхнем уровне модуля и тем, что обозначены как global.
  4. Если поиск не дает результатов, интерпретатор ищет имена во встроенной области видимости языка Python.

Рассмотрим наглядный пример:

  • >>>L = 85
  • >>>R = 23
  • >>>def пример_2(K):
  • R = 10
  • C = L + K+R
  • return C
  • >>>пример_2(5)

Переменные L и R находятся на верхнем уровне и являются глобальными именами. R, C и K - это локальные переменные, так как присваивание значения происходит внутри инструкции def.

Интерпретатор сначала выполняет операцию сложения для локальных R, C и K, игнорируя переменную R вне инструкции def. Потом ищет L, и не найдя ее среди имен local, переходит на верхний уровень.

Что такое lambda

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

Как и def, lambda создает функцию, которую можно будет в дальнейшем вызвать, но не связывает ее с каким-нибудь именем. На практике lambda используют, когда нужно отложить выполнение фрагмента кода.

Основы лямбда-выражений

По внешнему виду lambda-выражения напоминают инструкции def. Вначале пишется ключевое слово lambda, потом аргументы, двоеточие и само выражение:

  • >>>f = lambda x, y, z: x + y + z
  • >>>f(2, 3, 4)

Тело лямбда представляет собой одно единственное выражение, а не блок инструкций. За счет этого lambda ограничена в возможностях и не настолько универсальна как def. В ней может быть реализована только логика, без циклов while или for.

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

Lambda-выражения очень удобно встраивать в программу. За счет небольшого размера они минимизируют и упрощают код. Но использование лямбда не является принципиальным. В Python 3 начинающим для работы будет достаточно инструкции def.

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

Чем меньше и специализированнее код функции, тем проще выбрать для нее понятное имя . Не бойтесь использовать длинные имена . Длинное содержательное имя лучше короткого невразумительного. Будьте последовательны в выборе имени. Используйте в имени функции те же словосочетания, глаголы и существительные, которые используются в ваших модулях. Создание функции производится с помощью инструкции def, как показано в следующем примере. Мы уже научились , давайте воспользуется знаниями тут.

# -*- coding: utf-8 -*- Phones = ["Nokia", "Samsung", "LG", "Sony"] def show_as_text(user_list): words = "" for value in user_list: words += str(value) + " " return words print "Phones: ", show_as_text(Phones) # Вернет: Phones: Nokia Samsung LG Sony

Достаточно простая структура функции. Название функции show_as_text, важно чтобы не совпадала с названием функции самого Python. Имя функции должна быть уникальна и по сравнению с переменными. Если функция будет иметь название get_values, и после нее в скрипте будет создана переменная с тем же именем, тогда вызов get_values(args) выдаст ошибку.

# -*- coding: utf-8 -*- def get_value(): return True a = 1 b = 3 get_value = "some text..." is_true = get_value()

Получим ошибку:

TypeError: "str" object is not callable Если потребуется вернуть из функции несколько значений, можно использовать кортеж. Создадим небольшой аналог игры Бинго! чтобы получить разные номера. # -*- coding: utf-8 -*- import random def bingo(): return (random.randint(0, 30), random.randint(0, 30), random.randint(0, 30)) Numbers = bingo() print "Первый: ", Numbers print "Второй: ", Numbers print "Третий: ", Numbers

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

Def connect(ip, port=8080): return str(ip) + " " + str(port) print connect("127.0.0.1") # Получим: 127.0.0.1 8080

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

Connect("сайт", 80)

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

Connect(port=80, host="сайт")

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

Num = 1 # Глабальная перемення def next_number(): global num personal_num = 999 num += 1 return num print next_number() # результат 2 # Попробуем получить значении локальной переменной personal_num print personal_num # Ошибка NameError: name "personal_num" is not defined

Именные функции, инструкция def

Функция в python - объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def.

Определим простейшую функцию:

Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.

Теперь мы ее можем вызвать:

>>> add(1, 10)

>>> add("abc", "def")

Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!):

>>> def newfunc(n):

Def myfunc(x):

Return x + n

Return myfunc

>>> new = newfunc(100) # new - это функция

>>> new(200)

Функция может и не заканчиваться инструкцией return, при этом функция вернет значениеNone:

>>> def func():

>>> print(func())

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

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

>>> def func(a, b, c=2): # c - необязательный аргумент

Return a + b + c

>>> func(1, 2) # a = 1, b = 2, c = 2 (по умолчанию)

>>> func(1, 2, 3) # a = 1, b = 2, c = 3

>>> func(a=1, b=3) # a = 1, b = 3, c = 2

>>> func(a=3, c=6) # a = 3, c = 6, b не определен

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes at least 2 arguments (2 given)

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

>>> def func(*args):

>>> func(1, 2, 3, "abc")

(1, 2, 3, "abc")

>>> func(1)

Как видно из примера, args - это кортежиз всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.

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

>>> def func(**kwargs):

Return kwargs

>>> func(a=1, b=2, c=3)

{"a": 1, "c": 3, "b": 2}

>>> func(a="python")

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

Анонимные функции, инструкция lambda

Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():

>>> func = lambda x, y: x + y

>>> func(1, 2)

>>> func("a", "b")

>>> (lambda x, y: x + y)(1, 2)

>>> (lambda x, y: x + y)("a", "b")

lambda функции, в отличие от обычной, не требуется инструкция return, а в остальном, ведет себя точно так же:

>>> func = lambda *args: args

>>> func(1, 2, 3, 4)

19. Понятие рекурсии, реализация в языке Python

В программировании рекурсия - вызов функции (процедуры) из неё же самой, непосредственно (простая рекурсия) или через другие функции (сложная или косвенная рекурсия), например, функция вызывает функцию, а функция- функцию. Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.

Проще сказать нельзя. Про рекурсии есть известная поговорка:

Чтобы понять рекурсию, нужно сперва понять рекурсию

Итак, питон позволяет работать с рекурсиями легко и непринужденно. Самый первый пример рекурсии, с которой сталкиваются большинство программистов - это нахождение факториала. Код может быть таким:

def factorial(n):

if n <= 1: return 1

else: return n * factorial(n - 1)

Как видно, мы записали инструкцию if else слегка необычным для питона способом, но это позволяется в данном случаее, ввиду того, что читабельность здесь не ухудшается, но не следует злоупотреблять таким стилем. И вообще, PEP8всех рассудит. :)

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

    Существует ограничение на глубину рекурсии. По умолчанию оно равно 1000.

    Для того, чтобы изменить это ограничение нужно вызвать функцию sys.setrecursionlimit(), а для просмотра текущего лимита sys.getrecursionlimit().

    Не смотря на это - существует ограничение размером стека, который устанавливается операционной системой.

    Рекурсия в Python не может использоваться в функциях-генераторах и сопрограммах. Однако, можно это поведение исправить, но лучше не стоит.

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

Также, всегда следует определять точки выхода из рекурсивных функций. Это как с циклами - бесконечный цикл может здорово «просадить» вашу операционную систему. И наконец, где лучше применять рекурсию, а где лучше воздержаться и обойтись, например циклами. Конечно, здесь многое зависит от задачи, но всегда следует помнить, что рекурсия в разы медленнее цикла. Так уж устроен питон, что вызов функции дорого вам обходится:) Вообще, в циклах не стоит вызывать функции, а уж рекурсивные функции и подавно.

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

Похожие статьи