======def (функция/метод)======
Последовательность инструкций, возвращающая некое значение.
В функцию могут быть переданы ноль и более аргументов, которые могут использоваться в теле функции.
Для возврата значения из функции используется инструкция return. Допускается использование нескольких return, в том числе для раннего выхода из функции.
Функции без инструкции return (равно как и с нею, но без указания аргумента) всё равно возвращают результат — None.
====Определение функции====
Функцию можно определить при помощи ключевого слова **def**, за которым должно следовать название функции и список её формальных параметров в круглых скобках. На следующих строках, выделенное отступом слева, должно располагаться тело функции.
Первой инструкцией в теле может быть литерал строки, который будет являться документацией для данной функции (строка документации — «docstring»). Некоторые утилиты и среды разработки используют такие строки для формирования интерактивной справки. Документировать код считается хорошим тоном.
def do_work(work, reverse=False):
"""Выполняет работу.
В случае удачного выполнения, возвращает True,
иначе — False.
:param list work: Список для работы.
:param bool reverse: Флаг. Следует ли сделать
работу в обратном порядке
:rtype: bool
"""
В примере выше объявляется функция **do_work**, с формальными параметрами **work** и **reverse**. Функция задокументирована (испольузется формат описания сигнатуры **reStructuredText**). Кроме строки документации тело функции не содержит инструкций, тем не менее функция возвращает **None**.
Определение функции описывает пользовательский «объект функции» и является исполняемой инструкцией. В ходе исполнения происходит связывание имени функции в текущем локальном пространстве имён (локальной символьной таблице) с «объектом функции» — обёрткой вокруг исполняемого кода функции. Объект функции содержит ссылку на текущее глобальное пространство имён, которое будет использовано при вызове функции. Объект функции может быть в последующем связан и с другим именем (это можно использовать для переименования функций и создания псевдонимов).
Само определение функции не вызывает исполнения кода из тела функции. Код исполняется только при вызове функции.
def print_yes():
print('yes')
print_yes() # yes
print_yes_alias = print_yes
print_yes_alias() # yes
Более того, ничто не мешает использовать «объект функции» как любой другой объект (например: передавать в функцию, использовать в качестве значения в словаре и т.п.).
def print_yes():
print('yes')
def print_no():
print('no')
my_functions = [print_yes, print_no]
for function in my_functions:
# Переменная function будет содержать объект
# функции. Его-то мы и вызываем в следующей строке.
function()
#yes
#no
В ходе исполнения функции формируется новая символьная таблица с локальными переменными функции: все назначения переменных оказываются в ней. При обращении к переменной, сначала производится попытка отыскать её в локальной символьной таблице, далее в таблицах обрамляющих функций, далее в глобальной таблице, и, наконец, в таблице встроенных имён.
Ввиду вышесказанного ссылаться на глобальные переменные внутри функции можно, а присвоить им значение (без использования инструкции global) нельзя.
MY_GLOBAL = 1
def set_global_1():
MY_GLOBAL = 2
def set_global_2():
global MY_GLOBAL
MY_GLOBAL = 2
print(MY_GLOBAL) # 1
set_global_1()
print(MY_GLOBAL) # 1
set_global_2()
print(MY_GLOBAL) # 2
Аргументы, с которыми была вызвана функция, также оказываются в её локальной символьной таблице.
В Питоне используется передача аргументов «по значению» (значением при этом всегда является ссылка на сам объект, но **не на его значение**). Однако, ввиду того, что в случаях, когда передаются изменяемые объекты, вызвавший увидит все изменения, сделанные вызываемым (например, при добавлении элементов в список), возможно лучше было бы назвать данный вид передачи **«передачей по ссылке на объект»**.
def mutate_list(a_list):
a_list.append(0)
return True
my_list = [1]
print(my_list) # [1]
mutate_list(my_list) # True
print(my_list) # [1, 0]
Когда функция вызывает другую функцию, для вызова создаётся новая локальная символьная таблица.
====Вложенные определения====
В Питоне можно вкладывать одно в другое не только определения функций (этим приёмом, в частости, пользуются при создании декораторов), но и классов (в случае необходимости).
def outer_func():
# Определение функции внутри другой
# функции.
def inner_func():
return 'some'
return inner_func()
print(outer_func()) # some
def get_my_class():
# Определение класса внутри определения
# функции.
class MyClass:
my_attr = 1
return MyClass
my_class = get_my_class()
print(my_class.my_attr) # 1
====позиционные аргументы====
Это аргументы, передаваемые в вызов в определённой последовательности (на определённых позициях), без указания их имён. Элементы объектов, поддерживающих итерирование, могут использоваться в качестве позиционных аргументов, если их распаковать при помощи *.
def custom_sum(a, b, c, d):
return a+b+c+d
print(custom_sum(1, 2, 3, 4)) #10
====Именованные аргументы====
Это аргументы, передаваемые в вызов при помощи имени (идентификатора), либо словаря с его распаковкой при помощи **.
def custom_sum(a, b=0, c=0, d=0):
return a+b+c+d
print(custom_sum(1)) #1
print(custom_sum(1, 3)) #4
print(custom_sum(1, c=1)) #2
====Переменное количество аргументов====
def custom_sum(*args):
sum = 0
for i in args:
sum +=i
return sum
print(custom_sum(1, 2, 3, 4))
def func(**kwargs):
print(kwargs)
func(a=1, b=4, c=45) # {'a': 1, 'b': 4, 'c': 45}
def func2(a, x, *args, **kwargs):
print(a)
print(x)
print(args)
print(kwargs)
func2(1, 2, 3, 4, b='test')
# 1
# 2
# (3, 4)
# {'b': 'test'}
====Документация к функциям====
def custom_sum(a, b):
"""
Возвращаем сумму аргументов a и b
:param a параметр а
:type a: int
:param b параметр b
:type b: int
:return:return type int
"""
return a+b
print(custom_sum(1, 2))