Функции Python
Узнайте, как определять и вызывать функции Python, использовать параметры, аргументы по умолчанию, *args, **kwargs, возвращаемые значения и docstrings.
Функция — это именованный, повторно используемый блок кода, выполняющий конкретную задачу. Функции позволяют написать логику один раз и вызывать её из любого места программы — делая код короче, удобнее для чтения и проще в тестировании. Эта глава охватывает всё необходимое для уверенной работы с функциями Python: определение, параметры, возвращаемые значения, аргументы по умолчанию, *args и **kwargs, область видимости, docstrings, аннотации типов, рекурсию и использование функций как объектов первого класса.
Определение функции
Используйте ключевое слово def, имя, круглые скобки и двоеточие. Тело функции выделяется одним уровнем отступа.
def greet(name):
print("Hello, " + name)Функция не выполняется до тех пор, пока вы её не вызовете. В момент определения ничего не происходит — Python лишь сохраняет объект функции под указанным именем.
Вызов функции
Передайте аргументы в скобках, соответствующие именам параметров в определении.
Возвращаемые значения
Функция может отправить результат обратно вызывающему коду с помощью оператора return. Без return Python возвращает None.
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8После выполнения return функция немедленно останавливается — любой код после него в теле той же функции недостижим.
Возврат нескольких значений
Python позволяет возвращать несколько значений в виде кортежа, который можно распаковать на стороне вызова.
import math
def circle_stats(radius):
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius
return area, circumference
area, circ = circle_stats(5)
print(round(area, 2)) # 78.54
print(round(circ, 2)) # 31.42Параметры и аргументы
| Термин | Значение |
|---|---|
| Параметр | Имя переменной в определении функции |
| Аргумент | Фактическое значение, передаваемое при вызове функции |
Python поддерживает несколько способов передачи аргументов.
Позиционные аргументы
Аргументы сопоставляются с параметрами по порядку.
def describe(name, age):
print(name, "is", age, "years old")
describe("Bob", 25) # Bob is 25 years oldИменованные аргументы
Аргументы можно передавать по имени, в любом порядке.
describe(age=25, name="Bob") # Bob is 25 years oldЗначения параметров по умолчанию
Укажите запасное значение, которое используется, когда вызывающий код не передаёт данный аргумент.
def greet(name="World"):
print("Hello, " + name)
greet() # Hello, World
greet("Alice") # Hello, AliceВажно: никогда не используйте изменяемый объект (список, словарь) в качестве значения по умолчанию — он создаётся один раз при определении функции и разделяется между всеми вызовами. Вместо этого используйте None в качестве значения по умолчанию и создавайте объект внутри тела функции.
# Correct pattern for a mutable default
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lstПроизвольное число позиционных аргументов (*args)
Добавьте префикс * к имени параметра, чтобы собрать любое количество позиционных аргументов в кортеж.
def total(*numbers):
return sum(numbers)
print(total(1, 2, 3)) # 6
print(total(10, 20)) # 30Произвольное число именованных аргументов (**kwargs)
Добавьте префикс **, чтобы собрать любое количество именованных аргументов в словарь.
def describe_person(**info):
for key, value in info.items():
print(key + ": " + str(value))
describe_person(name="Alice", age=30, city="Paris")
# name: Alice
# age: 30
# city: ParisКомбинирование типов параметров
При смешивании типов параметров порядок должен быть следующим: позиционные, *args, только именованные, **kwargs.
def log(level, *messages, separator=" | ", **meta):
print(level.upper(), separator.join(messages), meta)
log("info", "started", "ready", separator=" — ", version="1.0")
# INFO started — ready {'version': '1.0'}Область видимости переменных
Правила области видимости Python следуют правилу LEGB: Local → Enclosing → Global → Built-in.
Переменная, определённая внутри функции, является локальной — к ней нельзя обратиться снаружи.
def my_func():
x = 10 # local to my_func
print(x)
my_func()
# print(x) # NameError: name 'x' is not definedЧтобы прочитать или изменить глобальную переменную внутри функции, объявите её с помощью global.
x = 10
def change_x():
global x
x = 20
change_x()
print(x) # 20Используйте global осторожно — функции, зависящие от глобального состояния, сложнее тестировать и переиспользовать. Подробнее об области видимости читайте в разделах Переменные Python и Глобальные переменные.
Docstrings
Docstring — это строковый литерал, размещённый сразу после строки def. Он документирует, что делает функция, что принимает и что возвращает. Python хранит его в атрибуте __doc__ функции, а такие инструменты, как help(), отображают его.
def add(a, b):
"""Return the sum of a and b.
Args:
a: First number.
b: Second number.
Returns:
The sum as a number.
"""
return a + b
print(add.__doc__)
# Return the sum of a and b.
# ...Аннотации типов
Аннотации типов (PEP 484) позволяют указывать типы параметров и возвращаемых значений. Python не проверяет их во время выполнения, но редакторы, линтеры и mypy используют их для раннего обнаружения ошибок.
def multiply(a: float, b: float) -> float:
return a * b
print(multiply(3, 4)) # 12
print(multiply(2.5, 2.0)) # 5.0Рекурсия
Функция может вызывать саму себя. Это называется рекурсией и полезно для задач с естественно рекурсивной структурой (деревья, факториалы и т. д.). Каждая рекурсивная функция должна иметь базовый случай, останавливающий рекурсию.
def factorial(n):
if n == 0 or n == 1: # base case
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
print(factorial(0)) # 1Python ограничивает глубину рекурсии (по умолчанию 1000), чтобы предотвратить переполнение стека. При глубокой рекурсии предпочтительнее использовать итеративный подход или sys.setrecursionlimit.
Функции как объекты первого класса
В Python функции являются объектами. Их можно хранить в переменных, передавать в качестве аргументов и возвращать из других функций.
def apply(func, value):
return func(value)
def double(n):
return n * 2
print(apply(double, 7)) # 14Это основа для лямбда-функций, функций высшего порядка и декораторов.
Встроенные функции и пользовательские функции
Python поставляется со множеством встроенных функций — print(), len(), range(), sum(), sorted() — которые всегда доступны без импорта. Пользовательские функции — это те, которые вы пишете с помощью def. Синтаксис вызова у них одинаковый.
Рекомендации
- Называйте функции глаголами:
calculate_tax()яснее, чемtax(). - Делайте одно дело: функция, которая проверяет, сохраняет и отправляет письмо — это три функции, ожидающие своего часа.
- Пишите docstring: даже одно предложение с описанием назначения имеет ценность.
- Избегайте побочных эффектов там, где это возможно: функции, которые возвращают значения и не изменяют глобальное состояние, легче тестировать.
- Держите сигнатуры короткими: более трёх-четырёх параметров — это сигнал сгруппировать связанные данные в класс или словарь.
- Используйте аннотации типов: они служат лёгкой документацией и позволяют выполнять статический анализ.