На языке Python (как, впрочем, и на других языках программирования) функция это блок кода, который работает только когда его вызывают. Вы можете передать в функцию данные для обработки, и эти данные называются параметрами (или аргументами). Функция может изменять внешние глобальные переменные и ничего не возвращать (на других языках такие функции часто называют процедурами, или подпрограммами), либо может возвращать какую-нибудь переменную в качестве результата своих вычислений.
Функции придумали не просто так, они нужны для того, чтобы сделать программу понятней и эффективней. Вот основные цели, которым служит использование функций:
1. Функции позволяют разбить программу на отдельные простые, понятные для понимания части. В результате программа упрощается. 2. Функции позволяют скрыть детали реализации основного алгоритма. Это тоже способствует упрощению понимания алгоритма программы. 3. Повторное использование написанного кода.
[Создание функции]
На языке Python функция создается с помощью ключевого слова def, после которого через пробел идет имя функции, например:
defmy_function():
print("Привет из функции!")
Чтобы код в функции заработал, её нужно вызвать по имени:
defmy_function():
print("Hello from a function")
my_function()
Аргументы функции. В предыдущем примере у функции my_function не было параметров. Однако функция может принимать один или несколько параметров, указываемых в круглых скобках. Если параметров несколько, то они перечисляются через запятую.
Термины 'параметр' и 'аргумент' могут использоваться для обозначения одного и того же: это какая-то порция информации (переменная, объект), передаваемой в функцию.
С точки зрения функции:
- Параметр это локальная в контексте тела функции переменная, перечисленная внутри круглых скобках определения функции. - Аргумент это значение, которое передается функции в момент её вызова.
Количество аргументов. По умолчанию функция должна быть вызвана с корректным количеством параметров, соответствующим её определению. Это значит, что если ваша функция ожидает 2 аргументов, то вы должны её вызвать с двумя аргументами, не больше и не меньше.
Например, эта функция ожидает 2 аргумента, и получает при вызове два аргумента:
Если вы попытаетесь передать в функцию my_function один параметр или три, то получите ошибку.
Произвольное количество параметров. Если вы не знаете, сколько параметров будет передано в функцию, то в определении функции добавьте звездочку перед именем параметра. Это позволяет передать в функцию кортеж аргументов (tuple), и к элементам кортежа можно обращаться как к элементам массива. Пример функции, которая напечатает все свои параметры через пробел:
defmy_function(*fparam):
for i inrange(len(fparam)):
print(fparam[i], '', end='')
print()
.. или так, что то же самое:
defmy_function(*fparam):
for i inrange(len(fparam)):
print(fparam[i], '', end='')
print()
Если эту функцию вызвать с разным количеством параметров:
Ключевые (или именованные) аргументы. В обычном синтаксисе вызова функции вы должны передавать аргументы в функцию в таком же порядке, в котором они были перечислены в определении функции. Однако вы также можете передавать аргументы в функции с помощью синтаксиса key = value, в этом случае порядок следования аргументов при вызове не имеет значения. Здесь key это имя параметра, которому передается значение value, Например:
Примечание: фраза "Keyword Arguments" (ключевые аргументы) в документации Python часто упоминается сокращением kwargs.
Произвольное количество ключевых аргументов. Если вы не знаете, сколько ключевых аргументов будет передаваться в функцию, то вы можете передать их в функцию, добавив в её определении две звездочки ** перед именем кортежа аргументов. Таким способом функция получит словарь аргументов (dictionary), и к нему можно будет обращаться соответствующим образом в теле функции:
Примечание: произвольное количество ключевых аргументов (Arbitrary Keyword Arguments) в документации Python часто сокращенно называют **kwargs.
Значение параметра по умолчанию. Следующий пример показывает, как использовать значение параметра по умолчанию. Если мы вызовем эту функцию без аргумента, то она будет использовать для него значение по умолчанию:
Хороший пример использования именованного параметра по умолчанию - параметр end функции print. По умолчанию параметр end принимает значение '\n', именно по этому каждый вызов print переводит позицию вывода на новую строку:
print('Вывод первой строки') print('Вывод второй строки')
Этот код ожидаемо напечатает:
Вывод первой строки Вывод второй строки
Но если мы хотим продолжать печатать на одной и той же строке несколькими вызовами print, то необходимо в качестве параметра передать end='':
Список в качестве аргумента. В функцию можно передавать любые данные в качестве аргумента (строка, массив, число, список, словарь, и т. д.), и это будет обрабатываться в теле функции соответственно типу переданного аргумента.
Например, если вы передадите в аргумент список, то он так и останется списком внутри функции, например:
defmy_function(food):
for x in food:
print(x)
fruits = ["яблоко", "банан", "вишня"]
my_function(fruits)
Этот код напечатает содержимое списка fruits:
яблоко банан вишня
[Возврат значения из функции]
Чтобы функция могла возвратить значение, используйте в ней оператор return, например:
Этот код выведет умноженное на 5 значение переданного в функцию аргумента:
15 25 45
[Оператор pass]
Определение функции не может быть пустым. Однако если по какой-то причине вы хотите оставить функцию без какой-либо реализации (временно создать заглушку функции, что может использоваться в целях отладки), то вы можете поместить в её тело оператор pass:
defmyfunction():
pass
[Только позиционные аргументы]
Вы можете указать, что у функции аргументы могут быть только позиционные, или указать, что они могут быть только ключевыми аргументами. Для того, чтобы аргументы были только позиционные, после имен аргументов добавьте , /:
defmy_function(x, /):
print(x)
my_function(3)
Если не указывать , /, то фактически разрешено использовать и ключевые аргументы, даже если функция ожидает позиционные аргументы, например:
defmy_function(x):
print(x)
my_function(x = 3)
Но если все-таки указать , /, то использование ключевых аргументов будет запрещено. Например, следующий код выдаст ошибку:
defmy_function(x, /):
print(x)
my_function(x = 3)
Traceback (most recent call last): File "c\temp\tt01.py", line 4, in < module> my_function(x = 3) ~~~~~~~~~~~^^^^^^^ TypeError: my_function() got some positional-only arguments passed as keyword arguments: 'x'
Только ключевые аргументы. Чтобы указать, что функция может иметь только ключевые аргументы, добавьте *, перед аргументами:
defmy_function(*, x):
print(x)
my_function(x = 3)
Без указания *, разрешается использовать позиционные аргументы, даже если функция ожидает ключевые аргументы:
defmy_function(x):
print(x)
my_function(3)
Однако с указанием *, вы получите ошибку, если попробуете отправить в функцию позиционный аргумент:
defmy_function(*, x):
print(x)
my_function(3)
Traceback (most recent call last): File "e:\aaa5\3\tt01.py", line 4, in < module> my_function(3) ~~~~~~~~~~~^^^ TypeError: my_function() takes 0 positional arguments but 1 was given
Комбинирование Positional-Only и Keyword-Only аргументов. Вы можете комбинировать оба типа аргументов в одной и той же функции.
Любые аргументы перед /, являются только позиционными (positional-only), и любые аргументы после *, являются только ключевымиe( keyword-only). Например:
defmy_function(a, b, /, *, c, d):
print(a + b + c + d)
my_function(5, 6, c = 7, d = 8)
[Локальные и глобальные переменные]
Локальные переменные. Переменные, которые объявлены внутри функции, являются локальными, т. е. они доступны только внутри тела функции. Например, следующий код выдаст ошибку:
definit_values():
a = 100
b = 200
init_values() print(a + b)
В следующем примере есть глобальная переменная a, и есть локальная переменная a, и это совершенно разные переменные, несмотря на то, что имена у них одинаковые:
definit_values():
a = 100
a = 0
init_values() print(a)
Этот код напечатает 0, потому что действие внутри init_values никак не повлияло на глобальную переменную a.
Параметр функции это тоже локальная переменная. Следующий пример тоже напечатает 0:
definit_values(a):
a = 100
a = 0
init_values(a) print(a)
Причина в том, что в функцию init_values передано значение глобальной переменной a, но не сама переменная, и не указатель на ней. Это не всегда так, что будет показано в следующем примере.
Изменение объектов, связанных с локальными переменными. Большой недостаток Python (если сравнивать с языком C) в том, что далеко не всегда хорошо видно, что передается в функцию - переменная или ссылка на неё (указатель). Если вы передадите в функцию объект, то будет передан не сам объект, а сслыка на него. Таким образом, действия внутри функции над переданным объектом приведут к тому, что будет изменена переменная глобального объекта. Например:
defappend_100(v):
v.append(100)
a = []
append_100(a) print(a)
Этот код напечатает:
[100]
Вот еще пример:
defappend_100(v):
v.append(100)
v = [5]
v.append(7)
a = []
append_100(a) print(a)
Этот пример также напечатает [100], несмотря на то, что в теле функции append_100 было присвание v = [5]. Это присваивание создало новую локальную переменную v, которая разорвала связь с указателем v, который был передан в функцию.
Глобальные переменные. Переменные, которые объявлены вне всяких функций, являются глобальными. Т. е. они доступны в любом месте программы, и внутри функций. В следующем примере переменная a является глобальной, и она доступна внутри функции print_val:
defprint_val()
print(a)
a = 5
print_val() # напечатает 5
Глобальные и локальные переменные. Нельзя смешивать внутри функции локальные и глобальные переменные под одинаковыми именами. Вот еще один пример:
defprint_val():
print(a)
a = 10print(a)
a = 5
print_val()
Запуск этого кода выдаст ошибку:
Traceback (most recent call last): File "e:\aaa5\3\tt02.py", line 7, in < module> print_val() ~~~~~~~~~^^ File "e:\aaa5\3\tt02.py", line 2, in print_val print(a) ^ UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
Причина в следующем: если мы внутри функции пытаемся изменить переменную по такому же имени, что и глобальная переменная, то эта переменная считается локальной. Переменная внутри функции не может считаться в каком-то месте глобальной, а в другом месте локальной, поэтому при её присваивании внутри функции переменная становится локальной. Следовательно, первый вызов print(a) пытается напечатать локальную переменную a, которая еще не инициализирована, и поэтому появляется ошибка.
[Рекурсия]
Python также допускает рекурсию функции, т. е. разрешена ситуация, когда функция саму себя.
Рекурсия это общеизвестная концепция математики и программирования. Она означает, что функция вызывает саму себя. В результате получается выгода в том, что внутри функции может осуществляться цикл по обработке данных, пока все данные не будут обработаны, либо пока не будет достигнут нужный результат.
Разработчик должен быть очень внимателен с рекурсией, потому что можно очень просто написать функцию, которая никогда не завершится, или функция израсходует все ресурсы памяти и/или процессора. Однако, если рекурсия реализована корректно, она дает очень эффективный и математически элегантный код.
Следующий пример определяет функцию tri_recursion(), которая вызывает саму себя. В качестве данных используется переменная k, которая декрементируется в каждом рекурсивном вызове. Рекурсия заканчивается, когда условие не больше 0 (например, когда результат функции станет 0).
deftri_recursion(k):
if(k > 0):
result = k + tri_recursion(k - 1)
print(result)
else:
result = 0return result
tri_recursion(6)
Этот код выведет следующее:
1 3 6 10 15 21
Новичку может потребоваться некоторое время, чтобы выяснить, как именно этот код работает, и лучший способ узнать это - протестировать и изменить его.