Как правильно объявлять функции в Python: синтаксис и примеры
Основные подходы к созданию функций
Наиболее распространённый и эффективный способ определить функцию в Python - использовать ключевое слово def, имя функции (например, f), круглые скобки с параметрами и двоеточие. Тело функции записывается с отступом в 4 пробела. Это позволяет многократно выполнять один и тот же блок кода, передавая разные аргументы.
def f():
print("Привет, мир!")
f()Def f python (определение функции f в python)
Привет, мир!
Def print python (определение функции print в python)
Такая конструкция не принимает аргументов и ничего не возвращает (возвращает None). Если требуется вернуть значение, используется оператор return.
Как определить функцию с параметрами?
Параметры перечисляются в скобках через запятую. При вызове функции передаются фактические аргументы.
def greet(name):
print(f"Привет, {name}!")
greet("Анна")Привет, Анна!
Как вернуть значение из функции?
Ключевое слово return завершает выполнение функции и передаёт объект обратно. Функция может вернуть одно значение, несколько (в виде кортежа) или ничего (вернётся None).
def add(a, b):
return a + b
result = add(3, 5)
print(result)8
Если return не указан, функция возвращает None.
Как задать параметры со значениями по умолчанию?
В заголовке функции можно указать значение по умолчанию для одного или нескольких параметров. Если аргумент не передан, используется значение по умолчанию.
def power(base, exp=2):
return base ** exp
print(power(3)) # 9
print(power(3, 3)) # 279 27
Как передать произвольное количество аргументов?
Синтаксис *args собирает позиционные аргументы в кортеж, а **kwargs - именованные в словарь.
def sum_all(*args):
return sum(args)
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print(sum_all(1, 2, 3, 4)) # 10
print_info(name="Анна", age=25)10 name: Анна age: 25
Как создать анонимную функцию (лямбда)?
Лямбда-выражение позволяет определить короткую функцию без def. Она содержит одно выражение, результат которого возвращается.
square = lambda x: x ** 2
print(square(5)) # 25
# Использование с filter
numbers = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]25 [2, 4]
Как использовать аннотации типов?
Аннотации указывают ожидаемые типы параметров и возвращаемого значения. Они не влияют на выполнение, но помогают инструментам статического анализа и документируют код.
def multiply(x: int, y: int) -> int:
return x * y
print(multiply(3, 4)) # 12Как определить вложенную (замыкающую) функцию?
Функция может быть объявлена внутри другой функции. Внутренняя функция видит переменные внешней (замыкание).
def make_adder(x):
def adder(y):
return x + y
return adder
add5 = make_adder(5)
print(add5(3)) # 8Как применить рекурсию?
Функция может вызывать саму себя. Обязательно должно быть базовое условие для остановки.
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120Как создать функцию-генератор?
Вместо return используется yield. Функция возвращает объект-генератор, который выдаёт значения по одному.
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
for num in count_up_to(3):
print(num)1 2 3
Как оформить документацию внутри функции?
Первая строка тела в виде строки (docstring) служит документацией. Она доступна через атрибут __doc__.
def my_function():
"""Эта функция ничего не делает, но документирована."""
pass
print(my_function.__doc__)Эта функция ничего не делает, но документирована.
Расширенные примеры
Функция с изменяемым аргументом по умолчанию (ловушка)
Следующая функция демонстрирует неожиданное поведение при использовании изменяемого объекта как значения по умолчанию.
def append_to(elem, target=[]):
target.append(elem)
return target
print(append_to(1)) # [1]
print(append_to(2)) # [1, 2], а не [2]
print(append_to(3, [])) # [3][1] [1, 2] [3]
Правильный способ - использовать None и создавать новый список внутри:
def append_to_fixed(elem, target=None):
if target is None:
target = []
target.append(elem)
return target
print(append_to_fixed(1)) # [1]
print(append_to_fixed(2)) # [2][1] [2]
Декоратор для логирования времени выполнения
Функции высшего порядка (декораторы) позволяют оборачивать другие функции, добавляя поведение.
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"Функция {func.__name__} выполнялась {elapsed:.4f} секунд")
return result
return wrapper
@timer
def slow_sum(a, b):
time.sleep(1)
return a + b
print(slow_sum(3, 4))Функция slow_sum выполнялась 1.0002 секунд 7
Генератор для чисел Фибоначчи
Генераторная функция экономит память, создавая последовательность по запросу.
def fibonacci(limit):
a, b = 0, 1
for _ in range(limit):
yield a
a, b = b, a + b
for fib in fibonacci(10):
print(fib, end=' ')0 1 1 2 3 5 8 13 21 34
Функция с проверкой типов через декоратор
Собственный декоратор может проверять аргументы на соответствие аннотациям.
def validate(func):
def wrapper(*args, **kwargs):
import inspect
sig = inspect.signature(func)
bound = sig.bind(*args, **kwargs)
for name, value in bound.arguments.items():
expected = sig.parameters[name].annotation
if expected is not inspect.Parameter.empty and not isinstance(value, expected):
raise TypeError(f"Аргумент {name} должен быть {expected.__name__}, а не {type(value).__name__}")
return func(*args, **kwargs)
return wrapper
@validate
def divide(x: int, y: int) -> float:
return x / y
print(divide(10, 3)) # работает
# print(divide(10, "3")) # TypeError3.3333333333333335