Функции

Содержание
Введение
Пример
def
Hello World!
type hints
Параметры и аргументы
Типы аргументов
Аргументы по умолчанию
Значения по умолчанию Mutable vs Immutable
return
Области видимости
Встроенные функции
Вызываемые объекты
Похожие статьи

Введение

Много интересного про функции можно прочитать в официальной документации

funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" assignment_expression NEWLINE
parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]] | parameter_list_no_posonly
parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]] | parameter_list_starargs
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]] | "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier

О чём говорит первая строка этой таблицы:

  1. Функция определяется с помощью ключевого слова def
  2. Перед def может быть объявлен декоратор

Пример использования

Создайте файл с раширением .py

Например functions_demo.py

Рассмотрим простейшую функцию, которая ничего не делает.

Чтобы её объявить используйте слово def затем придумайте название - например lazy поставьте круглые скобки () и двоеточие

Общий синтаксис следующий

def имя_функции(): какой-то код

В нашем случае получается

def lazy(): pass

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

Наша функция создана, иначе говоря объявлена. Это значит, что она существует где-то в коде и может что-то сделать.

Но не делает. Чтобы функция что-то делала её нужно вызвать. В нашем случае достаточно написать её имя и круглые скобки.

lazy()

python functions_demo.py

Если никаких ошибок не допущено вывод будет пустым

def

Ключевое слово def используется для определения новых функций.

Оно связывает объект функции с именем

Выполняется в runtime

Hello World!

Объявим и вызовем функцию, которая пишет Hello World!

def hello(): print("Hello World!") hello()

python functions_demo.py

Hello World!

Функцию не обязательно писать в одну строку. Лучше после двоеточия перейти на новую строку и сделать отступ из четырёх пробелов.

def hello(): print("Hello World!") hello()

python functions_demo.py

Hello World!

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

def sum(first, second): print(first + second) sum(3,4)

python functions_demo.py

7

Изображение баннера

type hints

В соответствии с PEP 484 рекомендуется указывать ожидаемые типы данных как для параметров, так и для возвращаемого значения

def sum(first: float, second: float) -> float: print(first + second) sum(3.0, 4.6)

python functions_demo.py

7.6

Никаких ограничений в самом Python эти подсказки не накладывают. Можно спокойно выполнить

sum("a", "b")

python functions_demo.py

И получить

ab

Подсказки нужны скорее для сторонней проверки, каким-либо инструментом, например mypy.

В фреймворке FastAPI указание или не указание type hints позволяет накладывать реальные ограничения на передаваемые агрументы.

Type hints используются не только в функциях но и, например при объявлении dataclass

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

Параметры и аргументы это почти одно и то же, но термин параметры применяют во время объявления функции а аргументы в момент вызова.

В некоторых источниках вместо термина параметры используется термин формальные аргументы (formal arguments)

Проще всего понять на примере

def add(a, b): return a+b add(2, 3)

a и b это параметры, а 2 и 3 это аргументы

Типы аргументов

Аргументы могут передаваться как позиционные (positional) и как именованные (keyword).

Позиционные аргументы

Позиционные аргументы сопоставляются с параметрами (parameter или formal argument) в соответсвии с порядком следования.

Пример передачи двух позиционных аргументов

a = sub(2, 3)

Предположим, функция sub() вычитает из первого аргумента второй.

sub(2, 3) = -1, sub(3, 2) = 1. Порядок имеет значение

Именованные аргументы

Именованные аргументы сопоставляются с параметрами по их имени.

Пример передачи двух именованных аргументов

a = div(divident=4, divisor=2)

Предположим, функция div() делит divident (делимое) на divisor (делитель). Порядок в котом передаются именованные аргументы не важен, значения будут присвоены по совпадении имён.

Способ, которым передаётся определённый аргумент, определяется при вызове функции.

Один и тот же аргумент может быть передан как позиционный и как именованный.

def main(): print(div()) print(div(9, 3)) print(div(divisor=5, divident=25)) def div(divident=2, divisor=1): return divident/divisor if __name__ == "__main__": main()

2.0 3.0 5.0

Сперва нужно передавать позиционные аргументы, затем именованные

# Вызов print(div(divisor=5, 25)) # Приведёт к ошибке

print(div(divisor=5, 25)) ^ SyntaxError: positional argument follows keyword argument

Ещё один пример здесь

Про передачу заранее неопределёного количества аргументов читайте статью *args **kwargs

Аргументы по умолчанию

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

# Arguments with default values must come # after those without default values. def banner(message, border="-"): line = border * len(message) print(line) print(message) print(line) banner("www.HeiHei.ru") # will use default "-" banner("www.TopBicycle.ru", "*") banner("www.KickBrains.ru", border="|")

python default_argumet_values.py

------------- www.HeiHei.ru ------------- ***************** www.TopBicycle.ru ***************** ||||||||||||||||| www.KickBrains.ru |||||||||||||||||

Значения по умолчанию

Mutable vs Immutable

В качестве значений по умолчанию лучше использовать неизменяемые (immutable) объекты.

Если и использовать изменяемые объекты, то нужно понимать, что они получают значения один раз - когда интерпретатор проходит объявление функции (def)

Пример

import time print("time.ctime()", time.ctime()) def show_default(arg=time.ctime()): print(arg) show_default() time.sleep(2) print("time.ctime()", time.ctime()) show_default()

time.ctime() Wed Jun 8 11:16:04 2022 Wed Jun 8 11:16:04 2022 time.ctime() Wed Jun 8 11:16:06 2022 Wed Jun 8 11:16:04 2022

Как видно из вывода в терминал - время уже ушло вперёд - 11:16:06 а функция как возвращала значение по умолчанию созданное в 11:16:04 так и продолжает это делать.

Рассмотрим ещё один пример. Теперь в качестве изменяемого объекта возьмём список

def add_spam(menu=[]): menu.append("spam") return menu breakfast = ['bacon', 'eggs'] print(add_spam(breakfast)) lunch = ['borsh'] print(add_spam(lunch)) print(add_spam()) print(add_spam()) print(add_spam())

['bacon', 'eggs', 'spam'] ['borsh', 'spam'] ['spam'] ['spam', 'spam'] ['spam', 'spam', 'spam']

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

Решить эту проблему можно сделав аргумент по умолчанию неизменяемым

def add_spam(menu=None): if menu is None: menu = [] menu.append("spam") return menu breakfast = ['bacon', 'eggs'] print(add_spam(breakfast)) lunch = ['borsh'] print(add_spam(lunch)) print(add_spam()) print(add_spam()) print(add_spam())

['bacon', 'eggs', 'spam'] ['borsh', 'spam'] ['spam'] ['spam'] ['spam']

return

Рассмотрим скрипт test_return.py

def test_return(): return "A" v = test_return() print(v)

python test_return.py

A

Всё выглядит хорошо, функция вернула строку, мы видим её в терминале.

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

tree return_ex

return_ex ├── parent_test_return.py └── test_return.py 0 directories, 2 files

# test_return def test_return(): return "A"

# parent_test_return from test_return import test_return v = test_return() print(v)

python parent_test_return.py

A

Области видимости

Рассмотрим четыре стандартные области видимости

Local: Внутри текущей функции
Enclosing: Внутри функции, вызывающей текущую
Global: Внутри модуля
Built-in: Встроенные в Python функции

Эта четвёрка описывается акронимом LEGB

Области видимости не имеют прямой связи с блоками кода.

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

count = 0 def show_count(): print(count) def set_count(c): count = c show_count() # 0 set_count(5) show_count() # 0

0 0

count = 0 def set_count(c): global count count = c show_count() # 0 set_count(5) show_count() # 0

0 5

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

Вызываемые объекты

Рассмотрим файл callables.py

def is_even(x): return x % 2 == 0 print(callable(is_even)) # True is_odd = lambda x: x % 2 == 1 print(callable(is_odd)) # True # Classes are callable print(callable(list)) # True # Methods are callable print(callable(list.append)) # True class CallMe: def __call__(self): print("Called!") my_call_me = CallMe() print(callable(my_call_me)) # True # Strings are not callable print(callable("This is no callable")) # False

python callables.py

True True True True True False

from functools import reduce import operator print(operator.add(8, 9)) print(reduce(operator.add, [1, 2, 3, 4, 5])) numbers = [1, 2, 3, 4, 5] accumulator = operator.add(numbers[0], numbers[1]) for item in numbers[2:]: accumulator = operator.add(accumulator, item) print(accumulator) def mul(x, y): print(f"mul {x} {y}") return x * y print(reduce(mul, range(1, 10))) # reduce(mul, []) # TypeErr reduce(mul, [1]) # returns element without calling reduce print(reduce(mul, [1])) # 1 # Initial value is added as a first accumulated value values = [1, 2, 3]

17 15 15 mul 1 2 mul 2 3 mul 6 4 mul 24 5 mul 120 6 mul 720 7 mul 5040 8 mul 40320 9 362880 1 6 0 6

Встроенные функции и теория

Встроенные функции Python
all()
any()
chr()
copy()
enumerate()
isinstance()
iter()
map()
next()
ord()
random()
sorted()
type()
uuid()
unichr()
zip()
Похожие статьи
Python
*args **kwargs
sys.argv: аргументы командной строки
Лямбда функции
Функции первого класса
Замыкания
Декораторы
Кэширование
if, elif, else
Циклы
Методы
Итерация
Генераторы
Генераторы: Maintaining State
Встроенные фукнции: all()zip()

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: